From 5018c2b40009258ed0691cbbb1dcc4d8ac4a809b Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 10 Jun 2021 11:55:27 +0800 Subject: import(life): ... --- .../operating-system-experiment/CMakeLists.txt | 3 +++ .../operating-system-experiment/Interlocked.cpp | 2 +- .../operating-system-experiment/Interlocked.hpp | 2 +- .../InterlockedAvoidDataRaceDemo.cpp | 28 ++++++++++++++++++++++ works/life/operating-system-experiment/Thread.cpp | 18 ++++++++++++-- works/life/operating-system-experiment/Thread.h | 12 ++-------- 6 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 works/life/operating-system-experiment/InterlockedAvoidDataRaceDemo.cpp 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 + +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 *>(lpParameter); @@ -139,5 +139,19 @@ void *ThreadProc(void *data) { } #endif -} // namespace details +} // namespace + +void Thread::CreateThread(std::function *proc) { +#ifdef CRU_WINDOWS + thread_handle_ = ::CreateThread(nullptr, 0, ThreadProc, + static_cast(proc), 0, &thread_id_); + assert(thread_handle_); +#else + thread_.reset(new pthread_t()); + auto c = pthread_create(thread_.get(), nullptr, ThreadProc, + static_cast(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 *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(p), 0, &thread_id_); - assert(thread_handle_); -#else - thread_.reset(new pthread_t()); - auto c = pthread_create(thread_.get(), nullptr, details::ThreadProc, - static_cast(p)); - assert(c == 0); -#endif + CreateThread(p); }; } // namespace cru -- cgit v1.2.3