From 8bdb5db67fa3eeda755511f91fd257bde548a18f Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 9 Jun 2021 22:28:01 +0800 Subject: import(life): ... --- works/life/operating-system-experiment/Base.h | 4 -- .../operating-system-experiment/CMakeLists.txt | 4 ++ works/life/operating-system-experiment/Thread.cpp | 53 ++++++++++++++++++++-- works/life/operating-system-experiment/Thread.h | 17 +++++++ 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/works/life/operating-system-experiment/Base.h b/works/life/operating-system-experiment/Base.h index b3ac1ee..6964c1c 100644 --- a/works/life/operating-system-experiment/Base.h +++ b/works/life/operating-system-experiment/Base.h @@ -5,10 +5,6 @@ #define CRU_WINDOWS 1 #endif -#ifdef CRU_WINDOWS -#include -#endif - #ifdef CRU_WINDOWS #ifdef CRU_EXPORT_API #define CRU_API __declspec(dllexport) diff --git a/works/life/operating-system-experiment/CMakeLists.txt b/works/life/operating-system-experiment/CMakeLists.txt index 2c46b0f..540574b 100644 --- a/works/life/operating-system-experiment/CMakeLists.txt +++ b/works/life/operating-system-experiment/CMakeLists.txt @@ -12,6 +12,10 @@ find_package(Microsoft.GSL CONFIG REQUIRED) add_library(cru_system SHARED Thread.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 diff --git a/works/life/operating-system-experiment/Thread.cpp b/works/life/operating-system-experiment/Thread.cpp index b91ca69..8230c1c 100644 --- a/works/life/operating-system-experiment/Thread.cpp +++ b/works/life/operating-system-experiment/Thread.cpp @@ -2,21 +2,36 @@ #include #include +#include #include namespace cru { Thread::Thread(Thread &&other) noexcept - : joined_(other.joined_), thread_handle_(other.thread_handle_) { + : detached_(other.detached_), joined_(other.joined_), +#ifdef CRU_WINDOWS + thread_handle_(other.thread_handle_) +#else + thread_(std::move(other.thread_)) +#endif +{ other.joined_ = false; +#ifdef CRU_WINDOWS other.thread_handle_ = nullptr; -} +#endif +} // namespace cru Thread &Thread::operator=(Thread &&other) noexcept { if (this != &other) { + detached_ = other.detached_; joined_ = other.joined_; +#ifdef CRU_WINDOWS thread_handle_ = other.thread_handle_; - other.joined_ = false; other.thread_handle_ = nullptr; +#else + thread_ = std::move(other.thread_); +#endif + other.detached_ = false; + other.joined_ = false; } return *this; @@ -25,13 +40,23 @@ Thread &Thread::operator=(Thread &&other) noexcept { Thread::~Thread() { Destroy(); } void Thread::Join() { - assert(thread_handle_); joined_ = true; +#ifdef CRU_WINDOWS + assert(thread_handle_); WaitForSingleObject(thread_handle_, INFINITE); +#else + assert(thread_); + auto c = pthread_join(*thread_, nullptr); + assert(c == 0); +#endif } void Thread::Detach() { +#ifdef CRU_WINDOWS assert(thread_handle_); +#else + assert(thread_); +#endif detached_ = true; } @@ -45,11 +70,22 @@ void Thread::swap(Thread &other) noexcept { } void Thread::Destroy() noexcept { - if (!detached_ && !joined_ && thread_handle_ != nullptr) { + if (!detached_ && !joined_ && +#ifdef CRU_WINDOWS + thread_handle_ != nullptr +#else + thread_ != nullptr +#endif + ) { std::terminate(); } else { + detached_ = false; joined_ = false; +#ifdef CRU_WINDOWS thread_handle_ = nullptr; +#else + thread_ = nullptr; +#endif } } @@ -62,6 +98,13 @@ DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) { return 0; } #else +void *ThreadProc(void *data) { + auto p = static_cast *>(data); + (*p)(); + delete p; + return nullptr; +} + #endif } // namespace details } // 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 c71c11f..79c1728 100644 --- a/works/life/operating-system-experiment/Thread.h +++ b/works/life/operating-system-experiment/Thread.h @@ -3,9 +3,17 @@ #include "Base.h" +#ifdef CRU_WINDOWS +#include +#else +#include +#endif + #ifdef __cplusplus +#include #include +#include #include #include #include @@ -38,6 +46,8 @@ private: #ifdef CRU_WINDOWS DWORD thread_id_ = 0; HANDLE thread_handle_ = nullptr; +#else + std::unique_ptr thread_; #endif }; @@ -45,6 +55,7 @@ namespace details { #ifdef CRU_WINDOWS CRU_API DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter); #else +void *ThreadProc(void *data); #endif } // namespace details @@ -59,6 +70,12 @@ Thread::Thread(Fn &&process, Args &&...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 }; } // namespace cru -- cgit v1.2.3