diff options
author | crupest <crupest@outlook.com> | 2021-06-11 10:43:00 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-06-11 10:43:00 +0800 |
commit | 0380cd595ee05773f78751aa7f2952b6ea105f7c (patch) | |
tree | eea9045c3749fdd5ad95ad272df396bd34280ab3 /works/life | |
parent | 5018c2b40009258ed0691cbbb1dcc4d8ac4a809b (diff) | |
download | crupest-0380cd595ee05773f78751aa7f2952b6ea105f7c.tar.gz crupest-0380cd595ee05773f78751aa7f2952b6ea105f7c.tar.bz2 crupest-0380cd595ee05773f78751aa7f2952b6ea105f7c.zip |
import(life): ...
Diffstat (limited to 'works/life')
4 files changed, 165 insertions, 1 deletions
diff --git a/works/life/operating-system-experiment/CMakeLists.txt b/works/life/operating-system-experiment/CMakeLists.txt index 8b4617f..c8afc24 100644 --- a/works/life/operating-system-experiment/CMakeLists.txt +++ b/works/life/operating-system-experiment/CMakeLists.txt @@ -9,7 +9,7 @@ set(CMAKE_CXX_STANDARD 17) find_package(fmt CONFIG REQUIRED)
find_package(Microsoft.GSL CONFIG REQUIRED)
-add_library(cru_system SHARED Thread.cpp Mutex.cpp Interlocked.cpp)
+add_library(cru_system SHARED Thread.cpp Mutex.cpp Interlocked.cpp Semaphore.cpp)
target_link_libraries(cru_system PUBLIC Microsoft.GSL::GSL fmt::fmt)
target_compile_definitions(cru_system PUBLIC CRU_EXPORT_API)
if(UNIX)
@@ -27,3 +27,7 @@ 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)
+
+add_executable(semaphore_avoid_data_race_demo SemaphoreAvoidDataRaceDemo.cpp)
+target_link_libraries(semaphore_avoid_data_race_demo PRIVATE cru_system)
+
diff --git a/works/life/operating-system-experiment/Semaphore.cpp b/works/life/operating-system-experiment/Semaphore.cpp new file mode 100644 index 0000000..e8221fd --- /dev/null +++ b/works/life/operating-system-experiment/Semaphore.cpp @@ -0,0 +1,78 @@ +#include "Semaphore.h" + +#include <cassert> + +#ifndef CRU_WINDOWS +#include <errno.h> +#endif + +namespace cru { +Semaphore::Semaphore(unsigned init_value) { +#ifdef CRU_WINDOWS +#else + semaphore_ = std::make_unique<sem_t>(); + auto c = sem_init(semaphore_.get(), 0, init_value); + assert(c == 0); +#endif +} + +Semaphore::Semaphore(Semaphore &&other) +#ifdef CRU_WINDOWS +#else + : semaphore_(std::move(other.semaphore_)) +#endif +{ +} + +Semaphore &Semaphore::operator=(Semaphore &&other) { + if (this != &other) { + Destroy(); +#ifdef CRU_WINDOWS +#else + semaphore_ = std::move(other.semaphore_); +#endif + } + return *this; +} + +Semaphore::~Semaphore() { Destroy(); } + +void Semaphore::P() { Acquire(); } +void Semaphore::V() { Release(); } + +void Semaphore::Acquire() { +#ifdef CRU_WINDOWS +#else + auto c = sem_wait(semaphore_.get()); + assert(c == 0); +#endif +} + +bool Semaphore::TryAcquire() { +#ifdef CRU_WINDOWS +#else + auto c = sem_trywait(semaphore_.get()); + assert((c == 0) || (c == -1 && errno == EAGAIN)); + return c == 0 ? true : false; +#endif +} + +void Semaphore::Release() { +#ifdef CRU_WINDOWS +#else + auto c = sem_post(semaphore_.get()); + assert(c == 0); +#endif +} + +void Semaphore::Destroy() { +#ifdef CRU_WINDOWS +#else + if (semaphore_ != nullptr) { + auto c = sem_destroy(semaphore_.get()); + assert(c == 0); + semaphore_ = nullptr; + } +#endif +} +} // namespace cru
\ No newline at end of file diff --git a/works/life/operating-system-experiment/Semaphore.h b/works/life/operating-system-experiment/Semaphore.h new file mode 100644 index 0000000..1d49b60 --- /dev/null +++ b/works/life/operating-system-experiment/Semaphore.h @@ -0,0 +1,46 @@ +#ifndef HEADER_SEMAPHORE_H +#define HEADER_SEMAPHORE_H + +#include "Base.h" + +#include <memory> + +#ifdef CRU_WINDOWS +#include <Windows.h> +#else +#include <semaphore.h> +#endif + +namespace cru { +class CRU_API Semaphore { +public: + explicit Semaphore(unsigned init_value = 1); + + Semaphore(const Semaphore &other) = delete; + Semaphore &operator=(const Semaphore &other) = delete; + + Semaphore(Semaphore &&other); + Semaphore &operator=(Semaphore &&other); + + ~Semaphore(); + +public: + void P(); + void V(); + + void Acquire(); + bool TryAcquire(); + void Release(); + +private: + void Destroy(); + +private: +#ifdef CRU_WINDOWS +#else + std::unique_ptr<sem_t> semaphore_; +#endif +}; +} // namespace cru + +#endif
\ No newline at end of file diff --git a/works/life/operating-system-experiment/SemaphoreAvoidDataRaceDemo.cpp b/works/life/operating-system-experiment/SemaphoreAvoidDataRaceDemo.cpp new file mode 100644 index 0000000..0068082 --- /dev/null +++ b/works/life/operating-system-experiment/SemaphoreAvoidDataRaceDemo.cpp @@ -0,0 +1,36 @@ +#include "Semaphore.h" +#include "Thread.h" + +#include <iostream> + +int main() { + unsigned data = 0; + + cru::Semaphore semaphore; + + cru::Thread t1([&data, &semaphore] { + for (int i = 0; i < 100000; i++) { + semaphore.P(); + data += 10; + semaphore.V(); + } + }); + + cru::Thread t2([&data, &semaphore] { + for (int i = 0; i < 100000; i++) { + semaphore.P(); + data += 10; + semaphore.V(); + } + }); + + 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; +} |