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/CMakeLists.txt | 8 ++- .../operating-system-experiment/DataRaceDemo.cpp | 27 ++++++++ works/life/operating-system-experiment/Mutex.cpp | 78 ++++++++++++++++++++++ works/life/operating-system-experiment/Mutex.h | 44 ++++++++++++ works/life/operating-system-experiment/Thread.cpp | 31 +++++++++ works/life/operating-system-experiment/Thread.h | 15 ++++- 6 files changed, 199 insertions(+), 4 deletions(-) create mode 100644 works/life/operating-system-experiment/DataRaceDemo.cpp create mode 100644 works/life/operating-system-experiment/Mutex.cpp create mode 100644 works/life/operating-system-experiment/Mutex.h diff --git a/works/life/operating-system-experiment/CMakeLists.txt b/works/life/operating-system-experiment/CMakeLists.txt index 540574b..806ec74 100644 --- a/works/life/operating-system-experiment/CMakeLists.txt +++ b/works/life/operating-system-experiment/CMakeLists.txt @@ -9,13 +9,15 @@ set(CMAKE_CXX_STANDARD 17) find_package(fmt CONFIG REQUIRED) find_package(Microsoft.GSL CONFIG REQUIRED) -add_library(cru_system SHARED Thread.cpp) +add_library(cru_system SHARED Thread.cpp Mutex.cpp) target_link_libraries(cru_system PUBLIC Microsoft.GSL::GSL fmt::fmt) target_compile_definitions(cru_system PUBLIC CRU_EXPORT_API) if(UNIX) target_link_libraries(cru_system PUBLIC pthread) endif() - add_executable(main main.cpp) -target_link_libraries(main PRIVATE cru_system) \ No newline at end of file +target_link_libraries(main PRIVATE cru_system) + +add_executable(data_race_demo DataRaceDemo.cpp) +target_link_libraries(data_race_demo PRIVATE cru_system) 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; +} diff --git a/works/life/operating-system-experiment/Mutex.cpp b/works/life/operating-system-experiment/Mutex.cpp new file mode 100644 index 0000000..6a91885 --- /dev/null +++ b/works/life/operating-system-experiment/Mutex.cpp @@ -0,0 +1,78 @@ +#include "Mutex.h" + +#include +#include + +#ifndef CRU_WINDOWS +#include +#endif + +namespace cru { +Mutex::Mutex() { +#ifdef CRU_WINDOWS +#else + mutex_ = std::make_unique(); + + auto c = pthread_mutex_init(mutex_.get(), nullptr); + assert(c == 0); +#endif +} + +Mutex::Mutex(Mutex &&other) +#ifdef CRU_WINDOWS +#else + : mutex_(std::move(other.mutex_)) +#endif +{ +} + +Mutex &Mutex::operator=(Mutex &&other) { + if (this != &other) { + Destroy(); + mutex_ = std::move(other.mutex_); + } + return *this; +} + +Mutex::~Mutex() { Destroy(); } + +void Mutex::Lock() { +#ifdef CRU_WINDOWS +#else + assert(mutex_); + auto c = pthread_mutex_lock(mutex_.get()); + assert(c == 0); +#endif +} + +bool Mutex::TryLock() { +#ifdef CRU_WINDOWS +#else + assert(mutex_); + auto c = pthread_mutex_trylock(mutex_.get()); + assert(c == 0 || c == EBUSY); + return c == 0 ? true : false; +#endif +} + +void Mutex::Unlock() { +#ifdef CRU_WINDOWS +#else + assert(mutex_); + auto c = pthread_mutex_unlock(mutex_.get()); + assert(c == 0); +#endif +} + +void Mutex::Destroy() { +#ifdef CRU_WINDOWS +#else + if (mutex_ != nullptr) { + auto c = pthread_mutex_destroy(mutex_.get()); + assert(c); + mutex_ = nullptr; + } +#endif +} + +} // namespace cru diff --git a/works/life/operating-system-experiment/Mutex.h b/works/life/operating-system-experiment/Mutex.h new file mode 100644 index 0000000..163d9ca --- /dev/null +++ b/works/life/operating-system-experiment/Mutex.h @@ -0,0 +1,44 @@ +#ifndef HEADER_MUTEX_H +#define HEADER_MUTEX_H + +#include "Base.h" + +#include + +#ifdef CRU_WINDOWS +#include +#else +#include +#endif + +namespace cru { +class CRU_API Mutex { +public: + Mutex(); + + Mutex(const Mutex &other) = delete; + Mutex &operator=(const Mutex &other) = delete; + + Mutex(Mutex &&other); + Mutex &operator=(Mutex &&other); + + ~Mutex(); + +public: + void Lock(); + bool TryLock(); + + void Unlock(); + +private: + void Destroy(); + +private: +#ifdef CRU_WINDOWS +#else + std::unique_ptr mutex_; +#endif +}; +} // namespace cru + +#endif \ No newline at end of file diff --git a/works/life/operating-system-experiment/Thread.cpp b/works/life/operating-system-experiment/Thread.cpp index 9d9f5dd..7e3c784 100644 --- a/works/life/operating-system-experiment/Thread.cpp +++ b/works/life/operating-system-experiment/Thread.cpp @@ -59,6 +59,36 @@ void Thread::Detach() { detached_ = true; } +#ifdef CRU_WINDOWS +DWORD +#else +pthread_t +#endif +Thread::GetNativeID() { +#ifdef CRU_WINDOWS + assert(thread_handle_); + return thread_id_; +#else + assert(thread_); + return *thread_; +#endif +} + +#ifdef CRU_WINDOWS +HANDLE +#else +pthread_t +#endif +Thread::GetNativeHandle() { +#ifdef CRU_WINDOWS + assert(thread_handle_); + return thread_handle_; +#else + assert(thread_); + return *thread_; +#endif +} + void Thread::swap(Thread &other) noexcept { #ifdef CRU_WINDOWS Thread temp = std::move(*this); @@ -81,6 +111,7 @@ void Thread::Destroy() noexcept { detached_ = false; joined_ = false; #ifdef CRU_WINDOWS + thread_id_ = 0; thread_handle_ = nullptr; #else thread_ = nullptr; diff --git a/works/life/operating-system-experiment/Thread.h b/works/life/operating-system-experiment/Thread.h index 69a402c..56fdcb0 100644 --- a/works/life/operating-system-experiment/Thread.h +++ b/works/life/operating-system-experiment/Thread.h @@ -18,7 +18,6 @@ #include #include #include -#include namespace cru { class CRU_API Thread { @@ -35,6 +34,20 @@ public: void Join(); void Detach(); +#ifdef CRU_WINDOWS + DWORD +#else + pthread_t +#endif + GetNativeID(); + +#ifdef CRU_WINDOWS + HANDLE +#else + pthread_t +#endif + GetNativeHandle(); + void swap(Thread &other) noexcept; private: -- cgit v1.2.3