diff options
Diffstat (limited to 'works/life/operating-system-experiment')
| -rw-r--r-- | works/life/operating-system-experiment/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | works/life/operating-system-experiment/DataRaceDemo.cpp | 27 | ||||
| -rw-r--r-- | works/life/operating-system-experiment/Mutex.cpp | 78 | ||||
| -rw-r--r-- | works/life/operating-system-experiment/Mutex.h | 44 | ||||
| -rw-r--r-- | works/life/operating-system-experiment/Thread.cpp | 31 | ||||
| -rw-r--r-- | works/life/operating-system-experiment/Thread.h | 15 | 
6 files changed, 199 insertions, 4 deletions
| 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 <iostream> + +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 <cassert> +#include <pthread.h> + +#ifndef CRU_WINDOWS +#include <errno.h> +#endif + +namespace cru { +Mutex::Mutex() { +#ifdef CRU_WINDOWS +#else +  mutex_ = std::make_unique<pthread_mutex_t>(); + +  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 <memory> + +#ifdef CRU_WINDOWS +#include <Windows.h> +#else +#include <pthread.h> +#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<pthread_mutex_t> 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 <type_traits>
  #include <utility>
  #include <vector>
 -#include <tuple>
  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:
 | 
