diff options
Diffstat (limited to 'works/life')
| -rw-r--r-- | works/life/operating-system-experiment/Base.h | 4 | ||||
| -rw-r--r-- | works/life/operating-system-experiment/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | works/life/operating-system-experiment/Thread.cpp | 53 | ||||
| -rw-r--r-- | 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 @@ -6,10 +6,6 @@  #endif
  #ifdef CRU_WINDOWS
 -#include <Windows.h>
 -#endif
 -
 -#ifdef CRU_WINDOWS
  #ifdef CRU_EXPORT_API
  #define CRU_API __declspec(dllexport)
  #else
 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 <cassert>
  #include <exception>
 +#include <pthread.h>
  #include <utility>
  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<std::function<void()> *>(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 <Windows.h>
 +#else
 +#include <pthread.h>
 +#endif
 +
  #ifdef __cplusplus
 +#include <cassert>
  #include <functional>
 +#include <memory>
  #include <tuple>
  #include <type_traits>
  #include <utility>
 @@ -38,6 +46,8 @@ private:  #ifdef CRU_WINDOWS
    DWORD thread_id_ = 0;
    HANDLE thread_handle_ = nullptr;
 +#else
 +  std::unique_ptr<pthread_t> 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<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
  };
  } // namespace cru
 | 
