diff options
Diffstat (limited to 'works')
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
 | 
