aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-06-10 11:35:29 +0800
committercrupest <crupest@outlook.com>2021-06-10 11:35:29 +0800
commitf532667d936500f50447d63333544f603ec06137 (patch)
treeab04f5afa2448e82baa82e409d5eb3fa6910a468
parentef593ba2d445af515214d63bfd3942be9d673467 (diff)
downloadcrupest-f532667d936500f50447d63333544f603ec06137.tar.gz
crupest-f532667d936500f50447d63333544f603ec06137.tar.bz2
crupest-f532667d936500f50447d63333544f603ec06137.zip
import(life): ...
-rw-r--r--works/life/operating-system-experiment/CMakeLists.txt3
-rw-r--r--works/life/operating-system-experiment/DataRaceDemo.cpp2
-rw-r--r--works/life/operating-system-experiment/Mutex.cpp23
-rw-r--r--works/life/operating-system-experiment/Mutex.h1
-rw-r--r--works/life/operating-system-experiment/MutexAvoidDataRaceDemo.cpp42
-rw-r--r--works/life/operating-system-experiment/Thread.cpp5
6 files changed, 73 insertions, 3 deletions
diff --git a/works/life/operating-system-experiment/CMakeLists.txt b/works/life/operating-system-experiment/CMakeLists.txt
index 806ec74..139d2ba 100644
--- a/works/life/operating-system-experiment/CMakeLists.txt
+++ b/works/life/operating-system-experiment/CMakeLists.txt
@@ -21,3 +21,6 @@ target_link_libraries(main PRIVATE cru_system)
add_executable(data_race_demo DataRaceDemo.cpp)
target_link_libraries(data_race_demo PRIVATE cru_system)
+
+add_executable(mutex_avoid_data_race_demo MutexAvoidDataRaceDemo.cpp)
+target_link_libraries(mutex_avoid_data_race_demo PRIVATE cru_system)
diff --git a/works/life/operating-system-experiment/DataRaceDemo.cpp b/works/life/operating-system-experiment/DataRaceDemo.cpp
index 9589eb3..a2f98d9 100644
--- a/works/life/operating-system-experiment/DataRaceDemo.cpp
+++ b/works/life/operating-system-experiment/DataRaceDemo.cpp
@@ -21,7 +21,7 @@ int main() {
t1.Join();
t2.Join();
std::cout << "Answer is " << data << ", which is "
- << (data == 200000 ? "correct" : "false") << '\n';
+ << (data == 2000000 ? "correct" : "false") << '\n';
return 0;
}
diff --git a/works/life/operating-system-experiment/Mutex.cpp b/works/life/operating-system-experiment/Mutex.cpp
index 6a91885..b7d0cb6 100644
--- a/works/life/operating-system-experiment/Mutex.cpp
+++ b/works/life/operating-system-experiment/Mutex.cpp
@@ -1,7 +1,6 @@
#include "Mutex.h"
#include <cassert>
-#include <pthread.h>
#ifndef CRU_WINDOWS
#include <errno.h>
@@ -10,6 +9,8 @@
namespace cru {
Mutex::Mutex() {
#ifdef CRU_WINDOWS
+ handle_ = CreateMutexW(nullptr, FALSE, nullptr);
+ assert(handle_);
#else
mutex_ = std::make_unique<pthread_mutex_t>();
@@ -20,16 +21,25 @@ Mutex::Mutex() {
Mutex::Mutex(Mutex &&other)
#ifdef CRU_WINDOWS
+ : handle_(other.handle_)
#else
: mutex_(std::move(other.mutex_))
#endif
{
+#ifdef CRU_WINDOWS
+ other.handle_ = nullptr;
+#endif
}
Mutex &Mutex::operator=(Mutex &&other) {
if (this != &other) {
Destroy();
+#ifdef CRU_WINDOWS
+ handle_ = other.handle_;
+ other.handle_ = nullptr;
+#else
mutex_ = std::move(other.mutex_);
+#endif
}
return *this;
}
@@ -38,6 +48,8 @@ Mutex::~Mutex() { Destroy(); }
void Mutex::Lock() {
#ifdef CRU_WINDOWS
+ auto c = WaitForSingleObject(handle_, INFINITE);
+ assert(c == WAIT_OBJECT_0);
#else
assert(mutex_);
auto c = pthread_mutex_lock(mutex_.get());
@@ -47,6 +59,9 @@ void Mutex::Lock() {
bool Mutex::TryLock() {
#ifdef CRU_WINDOWS
+ auto c = WaitForSingleObject(handle_, 0);
+ assert(c == WAIT_OBJECT_0 || c == WAIT_TIMEOUT);
+ return c == WAIT_OBJECT_0 ? true : false;
#else
assert(mutex_);
auto c = pthread_mutex_trylock(mutex_.get());
@@ -57,6 +72,8 @@ bool Mutex::TryLock() {
void Mutex::Unlock() {
#ifdef CRU_WINDOWS
+ auto c = ReleaseMutex(handle_);
+ assert(c);
#else
assert(mutex_);
auto c = pthread_mutex_unlock(mutex_.get());
@@ -66,6 +83,10 @@ void Mutex::Unlock() {
void Mutex::Destroy() {
#ifdef CRU_WINDOWS
+ if (handle_ != nullptr) {
+ auto c = CloseHandle(handle_);
+ assert(c);
+ }
#else
if (mutex_ != nullptr) {
auto c = pthread_mutex_destroy(mutex_.get());
diff --git a/works/life/operating-system-experiment/Mutex.h b/works/life/operating-system-experiment/Mutex.h
index 163d9ca..d561f1a 100644
--- a/works/life/operating-system-experiment/Mutex.h
+++ b/works/life/operating-system-experiment/Mutex.h
@@ -35,6 +35,7 @@ private:
private:
#ifdef CRU_WINDOWS
+ HANDLE handle_;
#else
std::unique_ptr<pthread_mutex_t> mutex_;
#endif
diff --git a/works/life/operating-system-experiment/MutexAvoidDataRaceDemo.cpp b/works/life/operating-system-experiment/MutexAvoidDataRaceDemo.cpp
new file mode 100644
index 0000000..81a7aa1
--- /dev/null
+++ b/works/life/operating-system-experiment/MutexAvoidDataRaceDemo.cpp
@@ -0,0 +1,42 @@
+#include "Mutex.h"
+#include "Thread.h"
+
+#include <iostream>
+
+int main() {
+
+ unsigned data = 0;
+ cru::Mutex mutex;
+ mutex.Lock();
+
+ cru::Thread t1([&data, &mutex] {
+ for (int i = 0; i < 100000; i++) {
+ mutex.Lock();
+ data += 10;
+ //std::cout << "Data is now: " << data << '\n';
+ mutex.Unlock();
+ }
+ });
+
+ cru::Thread t2([&data, &mutex] {
+ for (int i = 0; i < 100000; i++) {
+ mutex.Lock();
+ data += 10;
+ //std::cout << "Data is now: " << data << '\n';
+ mutex.Unlock();
+ }
+ });
+
+ std::cout << "Created thread: " << t1.GetNativeID() << '\n';
+ std::cout << "Created thread: " << t2.GetNativeID() << '\n';
+
+ mutex.Unlock();
+
+ t1.Join();
+ t2.Join();
+
+ std::cout << "Answer is " << data << ", which is "
+ << (data == 2000000 ? "correct" : "false") << '\n';
+
+ return 0;
+}
diff --git a/works/life/operating-system-experiment/Thread.cpp b/works/life/operating-system-experiment/Thread.cpp
index 7e3c784..a5f526d 100644
--- a/works/life/operating-system-experiment/Thread.cpp
+++ b/works/life/operating-system-experiment/Thread.cpp
@@ -112,7 +112,10 @@ void Thread::Destroy() noexcept {
joined_ = false;
#ifdef CRU_WINDOWS
thread_id_ = 0;
- thread_handle_ = nullptr;
+ if (thread_handle_ != nullptr) {
+ CloseHandle(thread_handle_);
+ thread_handle_ = nullptr;
+ }
#else
thread_ = nullptr;
#endif