From ef593ba2d445af515214d63bfd3942be9d673467 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 10 Jun 2021 11:12:25 +0800 Subject: import(life): ... --- .../operating-system-experiment/DataRaceDemo.cpp | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 works/life/operating-system-experiment/DataRaceDemo.cpp (limited to 'works/life/operating-system-experiment/DataRaceDemo.cpp') diff --git a/works/life/operating-system-experiment/DataRaceDemo.cpp b/works/life/operating-system-experiment/DataRaceDemo.cpp new file mode 100644 index 0000000..9589eb3 --- /dev/null +++ b/works/life/operating-system-experiment/DataRaceDemo.cpp @@ -0,0 +1,27 @@ +#include "Thread.h" + +#include + +int main() { + unsigned data = 0; + + cru::Thread t1([&data] { + for (int i = 0; i < 100000; i++) + data += 10; + }); + + cru::Thread t2([&data] { + for (int i = 0; i < 100000; i++) + data += 10; + }); + + std::cout << "Created thread: " << t1.GetNativeID() << '\n'; + std::cout << "Created thread: " << t2.GetNativeID() << '\n'; + + t1.Join(); + t2.Join(); + std::cout << "Answer is " << data << ", which is " + << (data == 200000 ? "correct" : "false") << '\n'; + + return 0; +} -- cgit v1.2.3 From f532667d936500f50447d63333544f603ec06137 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 10 Jun 2021 11:35:29 +0800 Subject: import(life): ... --- .../operating-system-experiment/CMakeLists.txt | 3 ++ .../operating-system-experiment/DataRaceDemo.cpp | 2 +- works/life/operating-system-experiment/Mutex.cpp | 23 +++++++++++- works/life/operating-system-experiment/Mutex.h | 1 + .../MutexAvoidDataRaceDemo.cpp | 42 ++++++++++++++++++++++ works/life/operating-system-experiment/Thread.cpp | 5 ++- 6 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 works/life/operating-system-experiment/MutexAvoidDataRaceDemo.cpp (limited to 'works/life/operating-system-experiment/DataRaceDemo.cpp') 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 -#include #ifndef CRU_WINDOWS #include @@ -10,6 +9,8 @@ namespace cru { Mutex::Mutex() { #ifdef CRU_WINDOWS + handle_ = CreateMutexW(nullptr, FALSE, nullptr); + assert(handle_); #else mutex_ = std::make_unique(); @@ -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 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 + +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 -- cgit v1.2.3