diff options
| author | crupest <crupest@outlook.com> | 2021-06-10 11:55:27 +0800 | 
|---|---|---|
| committer | crupest <crupest@outlook.com> | 2021-06-10 11:55:27 +0800 | 
| commit | 5018c2b40009258ed0691cbbb1dcc4d8ac4a809b (patch) | |
| tree | 1c4269b73b0473f47b98ca260676dbec1460791f | |
| parent | 06c91dd3a3d17bd1f884c7e322fd7701a95ce7a9 (diff) | |
| download | crupest-5018c2b40009258ed0691cbbb1dcc4d8ac4a809b.tar.gz crupest-5018c2b40009258ed0691cbbb1dcc4d8ac4a809b.tar.bz2 crupest-5018c2b40009258ed0691cbbb1dcc4d8ac4a809b.zip  | |
import(life): ...
6 files changed, 51 insertions, 14 deletions
diff --git a/works/life/operating-system-experiment/CMakeLists.txt b/works/life/operating-system-experiment/CMakeLists.txt index bd50319..8b4617f 100644 --- a/works/life/operating-system-experiment/CMakeLists.txt +++ b/works/life/operating-system-experiment/CMakeLists.txt @@ -24,3 +24,6 @@ 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)
 +
 +add_executable(interlocked_avoid_data_race_demo InterlockedAvoidDataRaceDemo.cpp)
 +target_link_libraries(interlocked_avoid_data_race_demo PRIVATE cru_system)
 diff --git a/works/life/operating-system-experiment/Interlocked.cpp b/works/life/operating-system-experiment/Interlocked.cpp index 1c0f638..7fc8c6b 100644 --- a/works/life/operating-system-experiment/Interlocked.cpp +++ b/works/life/operating-system-experiment/Interlocked.cpp @@ -6,7 +6,7 @@  #endif
  namespace cru {
 -void InterlockedAdd(volatile long long *v, long long a) {
 +void CruInterlockedAdd(volatile long long *v, long long a) {
  #ifdef CRU_WINDOWS
    InterlockedAdd64(v, a);
  #else
 diff --git a/works/life/operating-system-experiment/Interlocked.hpp b/works/life/operating-system-experiment/Interlocked.hpp index aa5dbfc..7e09b60 100644 --- a/works/life/operating-system-experiment/Interlocked.hpp +++ b/works/life/operating-system-experiment/Interlocked.hpp @@ -4,7 +4,7 @@  #include "Base.h"
  namespace cru {
 -CRU_API void InterlockedAdd(volatile long long *v, long long a);
 +CRU_API void CruInterlockedAdd(volatile long long *v, long long a);
  }
  #endif
 diff --git a/works/life/operating-system-experiment/InterlockedAvoidDataRaceDemo.cpp b/works/life/operating-system-experiment/InterlockedAvoidDataRaceDemo.cpp new file mode 100644 index 0000000..91d6d50 --- /dev/null +++ b/works/life/operating-system-experiment/InterlockedAvoidDataRaceDemo.cpp @@ -0,0 +1,28 @@ +#include "Interlocked.hpp" +#include "Thread.h" + +#include <iostream> + +int main() { +  volatile long long data = 0; + +  cru::Thread t1([&data] { +    for (int i = 0; i < 100000; i++) +      cru::CruInterlockedAdd(&data, 10); +  }); + +  cru::Thread t2([&data] { +    for (int i = 0; i < 100000; i++) +      cru::CruInterlockedAdd(&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 == 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 a5f526d..657c69f 100644 --- a/works/life/operating-system-experiment/Thread.cpp +++ b/works/life/operating-system-experiment/Thread.cpp @@ -122,7 +122,7 @@ void Thread::Destroy() noexcept {    }
  }
 -namespace details {
 +namespace {
  #ifdef CRU_WINDOWS
  DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) {
    auto p = static_cast<std::function<void()> *>(lpParameter);
 @@ -139,5 +139,19 @@ void *ThreadProc(void *data) {  }
  #endif
 -} // namespace details
 +} // namespace
 +
 +void Thread::CreateThread(std::function<void()> *proc) {
 +#ifdef CRU_WINDOWS
 +  thread_handle_ = ::CreateThread(nullptr, 0, ThreadProc,
 +                                  static_cast<void *>(proc), 0, &thread_id_);
 +  assert(thread_handle_);
 +#else
 +  thread_.reset(new pthread_t());
 +  auto c = pthread_create(thread_.get(), nullptr, ThreadProc,
 +                          static_cast<void *>(proc));
 +  assert(c == 0);
 +#endif
 +};
 +
  } // namespace cru
\ No newline at end of file diff --git a/works/life/operating-system-experiment/Thread.h b/works/life/operating-system-experiment/Thread.h index 56fdcb0..735407c 100644 --- a/works/life/operating-system-experiment/Thread.h +++ b/works/life/operating-system-experiment/Thread.h @@ -52,6 +52,7 @@ public:  private:
    void Destroy() noexcept;
 +  void CreateThread(std::function<void()> *proc);
  private:
    bool detached_ = false;
 @@ -81,16 +82,7 @@ Thread::Thread(Fn &&process, Args &&...args) {          std::apply(process, std::move(args));
        });
 -#ifdef CRU_WINDOWS
 -  thread_handle_ = ::CreateThread(nullptr, 0, &::cru::details::ThreadProc,
 -                                  static_cast<void *>(p), 0, &thread_id_);
 -  assert(thread_handle_);
 -#else
 -  thread_.reset(new pthread_t());
 -  auto c = pthread_create(thread_.get(), nullptr, details::ThreadProc,
 -                          static_cast<void *>(p));
 -  assert(c == 0);
 -#endif
 +  CreateThread(p);
  };
  } // namespace cru
  | 
