diff options
Diffstat (limited to 'works/life/operating-system-experiment')
22 files changed, 0 insertions, 977 deletions
diff --git a/works/life/operating-system-experiment/.gitignore b/works/life/operating-system-experiment/.gitignore deleted file mode 100644 index 502724c..0000000 --- a/works/life/operating-system-experiment/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.exe
-*.pdb
-.cache
-build
-compile_commands.json
\ No newline at end of file diff --git a/works/life/operating-system-experiment/Base.h b/works/life/operating-system-experiment/Base.h deleted file mode 100644 index 6964c1c..0000000 --- a/works/life/operating-system-experiment/Base.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef HEADER_BASE_H
-#define HEADER_BASE_H
-
-#ifdef _WIN32
-#define CRU_WINDOWS 1
-#endif
-
-#ifdef CRU_WINDOWS
-#ifdef CRU_EXPORT_API
-#define CRU_API __declspec(dllexport)
-#else
-#define CRU_API __declspec(dllimport)
-#endif
-#else
-#define CRU_API
-#endif
-
-#endif
\ No newline at end of file diff --git a/works/life/operating-system-experiment/CMakeLists.txt b/works/life/operating-system-experiment/CMakeLists.txt deleted file mode 100644 index 79fe786..0000000 --- a/works/life/operating-system-experiment/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.20)
-
-set(CMAKE_TOOLCHAIN_FILE $ENV{VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake
- CACHE STRING "Vcpkg toolchain file")
-
-project(operating-system-experiment)
-
-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 Semaphore.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)
-
-add_executable(data_race_demo DataRaceDemo.cpp)
-target_link_libraries(data_race_demo PRIVATE cru_system)
-
-add_executable(mutex_avoid_data_race_demo MutexAvoidDataRaceDemo.cpp)
-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)
-
-add_executable(parallel_calculation_demo ParallelCalculationDemo.cpp)
-target_link_libraries(parallel_calculation_demo PRIVATE cru_system)
-
-add_executable(dead_lock_detection_demo DeadLockDetectionDemo.cpp)
diff --git a/works/life/operating-system-experiment/DataRaceDemo.cpp b/works/life/operating-system-experiment/DataRaceDemo.cpp deleted file mode 100644 index a2f98d9..0000000 --- a/works/life/operating-system-experiment/DataRaceDemo.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#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 == 2000000 ? "correct" : "false") << '\n'; - - return 0; -} diff --git a/works/life/operating-system-experiment/DeadLockDetectionDemo.cpp b/works/life/operating-system-experiment/DeadLockDetectionDemo.cpp deleted file mode 100644 index bea2b43..0000000 --- a/works/life/operating-system-experiment/DeadLockDetectionDemo.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Demo使用方法:
-// 本程序采用标准C++11代码写成,请使用支持C++11的编译器编译。
-//
-// 程序接受的输入为n个整数对,其中1-10000表示进程,10001及以上表示锁,顺序很重要:
-// 1 10001 -> process 1 is acquiring or waiting for lock 1
-// 10001 1 -> lock 1 is owned by process 1
-//
-// 建议采用重定向输入至文件的方式输入,提供4个典型情况的测试数据。
-//
-
-#include <iostream>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-const int LOCK_START_INDEX = 10000;
-
-struct Node {
- int id;
-};
-
-bool operator==(const Node &left, const Node &right) {
- return left.id == right.id;
-}
-
-template <> struct std::hash<Node> {
- std::size_t operator()(const Node &node) const {
- return std::hash<int>{}(node.id);
- }
-};
-
-std::ostream &operator<<(std::ostream &left, const Node &right) {
- left << (right.id > LOCK_START_INDEX ? "lock" : "process") << ' '
- << (right.id > LOCK_START_INDEX ? right.id - LOCK_START_INDEX
- : right.id);
- return left;
-}
-
-bool dfs(
- const Node *root,
- std::unordered_map<const Node *, std::unordered_set<const Node *>> &edges,
- std::unordered_map<const Node *, bool> &visited) {
-
- if (visited[root]) {
- std::cout << "Ohhhhhh, it is already visited!\n";
- return true;
- }
-
- visited[root] = true;
- auto r = edges.find(root);
- if (r != edges.cend())
- for (auto n : r->second) {
- std::cout << "from " << *root << " go to " << *n << "\n";
- if (dfs(n, edges, visited))
- return true;
- std::cout << "from " << *n << " back to " << *root << "\n";
- }
-
- edges.erase(root);
- return false;
-}
-
-int main() {
- std::vector<int> ns;
-
- while (std::cin) {
- int n;
- std::cin >> n;
- if (std::cin)
- ns.push_back(n);
- }
-
- if (!std::cin.eof()) {
- std::cerr << "Failed to parse input.\n";
- return -1;
- }
-
- if (ns.size() % 2 != 0) {
- std::cerr << "Input integer number must be even.\n";
- return -1;
- }
-
- std::unordered_set<Node> nodes;
- std::unordered_map<const Node *, std::unordered_set<const Node *>> edges;
-
- for (int i = 0; i < ns.size(); i += 2) {
- int p = ns[i];
- int l = ns[i + 1];
- auto r1 = nodes.insert({p});
- auto r2 = nodes.insert({l});
- edges[&(*r1.first)].insert(&(*r2.first));
- }
-
- bool h = false;
-
- while (!edges.empty()) {
- auto n = edges.cbegin()->first;
- std::unordered_map<const Node *, bool> visited;
- std::cout << "Begin to detect child graph containing '" << *n << "'.\n";
- if (dfs(n, edges, visited)) {
- h = true;
- break;
- }
- }
-
- if (h) {
- std::cout << "Cycle, aka dead lock, detected.\n";
- } else {
- std::cout << "You are free of dead lock!!!\n";
- }
-
- return 0;
-}
diff --git a/works/life/operating-system-experiment/DeadLockTestData1.txt b/works/life/operating-system-experiment/DeadLockTestData1.txt deleted file mode 100644 index 0c8dd14..0000000 --- a/works/life/operating-system-experiment/DeadLockTestData1.txt +++ /dev/null @@ -1,4 +0,0 @@ -1 10001
-2 10001
-3 10001
-4 10001
diff --git a/works/life/operating-system-experiment/DeadLockTestData2.txt b/works/life/operating-system-experiment/DeadLockTestData2.txt deleted file mode 100644 index d632f2a..0000000 --- a/works/life/operating-system-experiment/DeadLockTestData2.txt +++ /dev/null @@ -1,4 +0,0 @@ -10001 1
-1 10002
-2 10001
-10002 2
diff --git a/works/life/operating-system-experiment/DeadLockTestData3.txt b/works/life/operating-system-experiment/DeadLockTestData3.txt deleted file mode 100644 index 1e1692d..0000000 --- a/works/life/operating-system-experiment/DeadLockTestData3.txt +++ /dev/null @@ -1,6 +0,0 @@ -1 10001
-10001 2
-2 10002
-10002 3
-3 10003
-10003 1
diff --git a/works/life/operating-system-experiment/DeadLockTestData4.txt b/works/life/operating-system-experiment/DeadLockTestData4.txt deleted file mode 100644 index d124102..0000000 --- a/works/life/operating-system-experiment/DeadLockTestData4.txt +++ /dev/null @@ -1,9 +0,0 @@ -1 10001
-2 10001
-3 10002
-3 10004
-10001 3
-4 10001
-4 10005
-10004 5
-10005 5
diff --git a/works/life/operating-system-experiment/Interlocked.cpp b/works/life/operating-system-experiment/Interlocked.cpp deleted file mode 100644 index 7fc8c6b..0000000 --- a/works/life/operating-system-experiment/Interlocked.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "Interlocked.hpp"
-
-#ifdef CRU_WINDOWS
-#include <Windows.h>
-#else
-#endif
-
-namespace cru {
-void CruInterlockedAdd(volatile long long *v, long long a) {
-#ifdef CRU_WINDOWS
- InterlockedAdd64(v, a);
-#else
- __sync_fetch_and_add(v, a);
-#endif
-}
-} // namespace cru
diff --git a/works/life/operating-system-experiment/Interlocked.hpp b/works/life/operating-system-experiment/Interlocked.hpp deleted file mode 100644 index 7e09b60..0000000 --- a/works/life/operating-system-experiment/Interlocked.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef HRADER_INTERLOCKED_H
-#define HRADER_INTERLOCKED_H
-
-#include "Base.h"
-
-namespace cru {
-CRU_API void CruInterlockedAdd(volatile long long *v, long long a);
-}
-
-#endif
diff --git a/works/life/operating-system-experiment/InterlockedAvoidDataRaceDemo.cpp b/works/life/operating-system-experiment/InterlockedAvoidDataRaceDemo.cpp deleted file mode 100644 index 91d6d50..0000000 --- a/works/life/operating-system-experiment/InterlockedAvoidDataRaceDemo.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "Interlocked.hpp" -#include "Thread.h" - -#include <iostream> - -int main() { - volatile long long data = 0; - - cru::Thread t1([&data] { - for (int i = 0; i < 100000; i++) - cru::CruInterlockedAdd(&data, 10); - }); - - cru::Thread t2([&data] { - for (int i = 0; i < 100000; i++) - cru::CruInterlockedAdd(&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 == 2000000 ? "correct" : "false") << '\n'; - - return 0; -} diff --git a/works/life/operating-system-experiment/Mutex.cpp b/works/life/operating-system-experiment/Mutex.cpp deleted file mode 100644 index 8acfdc5..0000000 --- a/works/life/operating-system-experiment/Mutex.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "Mutex.h" - -#include <cassert> - -#ifndef CRU_WINDOWS -#include <errno.h> -#endif - -namespace cru { -Mutex::Mutex() { -#ifdef CRU_WINDOWS - handle_ = CreateMutexW(nullptr, FALSE, nullptr); - assert(handle_); -#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 - : handle_(other.handle_) -#else - : mutex_(std::move(other.mutex_)) -#endif -{ -#ifdef CRU_WINDOWS - other.handle_ = nullptr; -#endif -} - -Mutex &Mutex::operator=(Mutex &&other) { - if (this != &other) { - Destroy(); -#ifdef CRU_WINDOWS - handle_ = other.handle_; - other.handle_ = nullptr; -#else - mutex_ = std::move(other.mutex_); -#endif - } - return *this; -} - -Mutex::~Mutex() { Destroy(); } - -void Mutex::Lock() { -#ifdef CRU_WINDOWS - auto c = WaitForSingleObject(handle_, INFINITE); - assert(c == WAIT_OBJECT_0); -#else - assert(mutex_); - auto c = pthread_mutex_lock(mutex_.get()); - assert(c == 0); -#endif -} - -bool Mutex::TryLock() { -#ifdef CRU_WINDOWS - auto c = WaitForSingleObject(handle_, 0); - assert(c == WAIT_OBJECT_0 || c == WAIT_TIMEOUT); - return c == WAIT_OBJECT_0 ? true : false; -#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 - auto c = ReleaseMutex(handle_); - assert(c); -#else - assert(mutex_); - auto c = pthread_mutex_unlock(mutex_.get()); - assert(c == 0); -#endif -} - -void Mutex::Destroy() { -#ifdef CRU_WINDOWS - if (handle_ != nullptr) { - auto c = CloseHandle(handle_); - assert(c); - handle_ = nullptr; - } -#else - if (mutex_ != nullptr) { - auto c = pthread_mutex_destroy(mutex_.get()); - assert(c == 0); - mutex_ = nullptr; - } -#endif -} - -} // namespace cru diff --git a/works/life/operating-system-experiment/Mutex.h b/works/life/operating-system-experiment/Mutex.h deleted file mode 100644 index d561f1a..0000000 --- a/works/life/operating-system-experiment/Mutex.h +++ /dev/null @@ -1,45 +0,0 @@ -#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 - HANDLE handle_; -#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/MutexAvoidDataRaceDemo.cpp b/works/life/operating-system-experiment/MutexAvoidDataRaceDemo.cpp deleted file mode 100644 index 81a7aa1..0000000 --- a/works/life/operating-system-experiment/MutexAvoidDataRaceDemo.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "Mutex.h"
-#include "Thread.h"
-
-#include <iostream>
-
-int main() {
-
- unsigned data = 0;
- cru::Mutex mutex;
- mutex.Lock();
-
- cru::Thread t1([&data, &mutex] {
- for (int i = 0; i < 100000; i++) {
- mutex.Lock();
- data += 10;
- //std::cout << "Data is now: " << data << '\n';
- mutex.Unlock();
- }
- });
-
- cru::Thread t2([&data, &mutex] {
- for (int i = 0; i < 100000; i++) {
- mutex.Lock();
- data += 10;
- //std::cout << "Data is now: " << data << '\n';
- mutex.Unlock();
- }
- });
-
- std::cout << "Created thread: " << t1.GetNativeID() << '\n';
- std::cout << "Created thread: " << t2.GetNativeID() << '\n';
-
- mutex.Unlock();
-
- t1.Join();
- t2.Join();
-
- std::cout << "Answer is " << data << ", which is "
- << (data == 2000000 ? "correct" : "false") << '\n';
-
- return 0;
-}
diff --git a/works/life/operating-system-experiment/ParallelCalculationDemo.cpp b/works/life/operating-system-experiment/ParallelCalculationDemo.cpp deleted file mode 100644 index 0174c55..0000000 --- a/works/life/operating-system-experiment/ParallelCalculationDemo.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "Thread.h" - -#include <iostream> - -const long long N = 1e9; - -int main(int argc, char **argv) { - int thread_number; - if (argc == 1) { - thread_number = 1; - } else if (argc == 2) { - thread_number = std::atoi(argv[1]); - if (thread_number <= 0) { - std::cerr << "Argument must be a positive integer.\n"; - return -1; - } - } else { - std::cerr << "Too many arguments.\n"; - return -1; - } - - std::cout << "Use " << thread_number << " threads to calculate sum of 1-" << N - << ".\n"; - - if (thread_number == 1) { - long long sum = 0; - for (long long i = 1; i <= 1e9; i++) { - sum += i; - } - std::cout << "Sum of 1-" << N << " is " << sum << '\n'; - } else { - std::vector<cru::Thread> threads(thread_number); - std::vector<long long> partial_sum(thread_number); - - long long step = N / thread_number; - - for (int i = 0; i < thread_number; i++) { - long long start = step * i; - long long end = step * (i + 1); - - long long &ps = partial_sum[i]; - - if (i == thread_number - 1) { - threads[i] = cru::Thread([&ps, start] { - long long sum = 0; - for (long long j = start; j <= N; j++) { - sum += j; - } - ps = sum; - }); - } else { - threads[i] = cru::Thread([&ps, start, end] { - long long sum = 0; - for (int j = start; j < end; j++) { - sum += j; - } - ps = sum; - }); - } - } - - for (auto &thread : threads) { - thread.Join(); - } - - long long sum = 0; - for (auto ps : partial_sum) { - sum += ps; - } - - std::cout << "Sum of 1-" << N << " is " << sum << '\n'; - } - - return 0; -} diff --git a/works/life/operating-system-experiment/Semaphore.cpp b/works/life/operating-system-experiment/Semaphore.cpp deleted file mode 100644 index aceef4d..0000000 --- a/works/life/operating-system-experiment/Semaphore.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "Semaphore.h" - -#include <cassert> - -#ifndef CRU_WINDOWS -#include <errno.h> -#endif - -namespace cru { -Semaphore::Semaphore(unsigned init_value) { -#ifdef CRU_WINDOWS - handle_ = CreateSemaphoreW(nullptr, init_value, 100, nullptr); - assert(handle_); -#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 - : handle_(other.handle_) -#else - : semaphore_(std::move(other.semaphore_)) -#endif -{ -#ifdef CRU_WINDOWS - other.handle_ = nullptr; -#endif -} - -Semaphore &Semaphore::operator=(Semaphore &&other) { - if (this != &other) { - Destroy(); -#ifdef CRU_WINDOWS - handle_ = other.handle_; - other.handle_ = nullptr; -#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 - auto c = WaitForSingleObject(handle_, INFINITE); - assert(c == WAIT_OBJECT_0); -#else - auto c = sem_wait(semaphore_.get()); - assert(c == 0); -#endif -} - -bool Semaphore::TryAcquire() { -#ifdef CRU_WINDOWS - auto c = WaitForSingleObject(handle_, 0); - assert(c == WAIT_OBJECT_0 || c == WAIT_TIMEOUT); - return c == WAIT_OBJECT_0 ? true : false; -#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 - auto c = ReleaseSemaphore(handle_, 1, nullptr); - assert(c); -#else - auto c = sem_post(semaphore_.get()); - assert(c == 0); -#endif -} - -void Semaphore::Destroy() { -#ifdef CRU_WINDOWS - if (handle_ != nullptr) { - auto c = CloseHandle(handle_); - assert(c); - handle_ = nullptr; - } -#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 deleted file mode 100644 index 430c036..0000000 --- a/works/life/operating-system-experiment/Semaphore.h +++ /dev/null @@ -1,47 +0,0 @@ -#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 - HANDLE handle_ = nullptr; -#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 deleted file mode 100644 index 0068082..0000000 --- a/works/life/operating-system-experiment/SemaphoreAvoidDataRaceDemo.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#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; -} diff --git a/works/life/operating-system-experiment/Thread.cpp b/works/life/operating-system-experiment/Thread.cpp deleted file mode 100644 index 0bc4c18..0000000 --- a/works/life/operating-system-experiment/Thread.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include "Thread.h"
-
-#include <cassert>
-#include <exception>
-#include <utility>
-
-namespace cru {
-Thread::Thread(Thread &&other) noexcept
- : 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.thread_handle_ = nullptr;
-#else
- thread_ = std::move(other.thread_);
-#endif
- other.detached_ = false;
- other.joined_ = false;
- }
-
- return *this;
-}
-
-Thread::~Thread() { Destroy(); }
-
-void Thread::Join() {
- 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;
-}
-
-#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);
- *this = std::move(other);
- other = std::move(temp);
-#else
-#endif
-}
-
-void Thread::Destroy() noexcept {
- if (!detached_ && !joined_ &&
-#ifdef CRU_WINDOWS
- thread_handle_ != nullptr
-#else
- thread_ != nullptr
-#endif
- ) {
- std::terminate();
- } else {
- detached_ = false;
- joined_ = false;
-#ifdef CRU_WINDOWS
- thread_id_ = 0;
- if (thread_handle_ != nullptr) {
- auto c = CloseHandle(thread_handle_);
- assert(c);
- thread_handle_ = nullptr;
- }
-#else
- thread_ = nullptr;
-#endif
- }
-}
-
-namespace {
-#ifdef CRU_WINDOWS
-DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) {
- auto p = static_cast<std::function<void()> *>(lpParameter);
- (*p)();
- delete p;
- return 0;
-}
-#else
-void *ThreadProc(void *data) {
- auto p = static_cast<std::function<void()> *>(data);
- (*p)();
- delete p;
- return nullptr;
-}
-
-#endif
-} // namespace
-
-void Thread::CreateThread(std::function<void()> *proc) {
-#ifdef CRU_WINDOWS
- thread_handle_ = ::CreateThread(nullptr, 0, ThreadProc,
- static_cast<void *>(proc), 0, &thread_id_);
- assert(thread_handle_);
-#else
- thread_.reset(new pthread_t());
- auto c = pthread_create(thread_.get(), nullptr, ThreadProc,
- static_cast<void *>(proc));
- assert(c == 0);
-#endif
-};
-
-} // 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 deleted file mode 100644 index 4ad1ef4..0000000 --- a/works/life/operating-system-experiment/Thread.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef HEADER_THREAD_H
-#define HEADER_THREAD_H
-
-#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>
-#include <vector>
-
-namespace cru {
-class CRU_API Thread {
-public:
- Thread() = default;
- template <typename Fn, typename... Args> Thread(Fn &&process, Args &&...args);
- Thread(const Thread &other) = delete;
- Thread(Thread &&other) noexcept;
- Thread &operator=(const Thread &other) = delete;
- Thread &operator=(Thread &&other) noexcept;
- ~Thread();
-
-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:
- void Destroy() noexcept;
- void CreateThread(std::function<void()> *proc);
-
-private:
- bool detached_ = false;
- bool joined_ = false;
-
-#ifdef CRU_WINDOWS
- DWORD thread_id_ = 0;
- HANDLE thread_handle_ = nullptr;
-#else
- std::unique_ptr<pthread_t> thread_;
-#endif
-};
-
-template <typename Fn, typename... Args>
-Thread::Thread(Fn &&process, Args &&...args) {
- std::tuple<std::decay_t<Args>...> a{std::forward<Args>(args)...};
- auto p = new std::function<void()>(
- [process = std::forward<Fn>(process), args = std::move(a)]() {
- std::apply(process, std::move(args));
- });
-
- CreateThread(p);
-};
-} // namespace cru
-
-#endif
-
-#endif
diff --git a/works/life/operating-system-experiment/main.cpp b/works/life/operating-system-experiment/main.cpp deleted file mode 100644 index ada8c85..0000000 --- a/works/life/operating-system-experiment/main.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "Thread.h"
-
-#include <iostream>
-#include <string>
-
-int main() {
- cru::Thread thread1([](const std::string &s) { std::cout << s; },
- "Hello world! 1\n");
- thread1.Join();
-
- cru::Thread thread2([](const std::string &s) { std::cout << s; },
- "Hello world! 2\n");
- thread2.Join();
-
- return 0;
-}
|