From d42dfdf4b903763997d47b6e2214c2ce33b9bf8e Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 9 Jun 2021 21:59:17 +0800 Subject: import(life): Add operating system experiement. --- works/life/operating-system-experiment/.gitignore | 5 ++ works/life/operating-system-experiment/Base.h | 22 +++++++ .../operating-system-experiment/CMakeLists.txt | 17 ++++++ works/life/operating-system-experiment/Thread.cpp | 67 +++++++++++++++++++++ works/life/operating-system-experiment/Thread.h | 68 ++++++++++++++++++++++ works/life/operating-system-experiment/main.cpp | 16 +++++ 6 files changed, 195 insertions(+) create mode 100644 works/life/operating-system-experiment/.gitignore create mode 100644 works/life/operating-system-experiment/Base.h create mode 100644 works/life/operating-system-experiment/CMakeLists.txt create mode 100644 works/life/operating-system-experiment/Thread.cpp create mode 100644 works/life/operating-system-experiment/Thread.h create mode 100644 works/life/operating-system-experiment/main.cpp diff --git a/works/life/operating-system-experiment/.gitignore b/works/life/operating-system-experiment/.gitignore new file mode 100644 index 0000000..502724c --- /dev/null +++ b/works/life/operating-system-experiment/.gitignore @@ -0,0 +1,5 @@ +*.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 new file mode 100644 index 0000000..b3ac1ee --- /dev/null +++ b/works/life/operating-system-experiment/Base.h @@ -0,0 +1,22 @@ +#ifndef HEADER_BASE_H +#define HEADER_BASE_H + +#ifdef _WIN32 +#define CRU_WINDOWS 1 +#endif + +#ifdef CRU_WINDOWS +#include +#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 new file mode 100644 index 0000000..2c46b0f --- /dev/null +++ b/works/life/operating-system-experiment/CMakeLists.txt @@ -0,0 +1,17 @@ +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) +target_link_libraries(cru_system PUBLIC Microsoft.GSL::GSL fmt::fmt) +target_compile_definitions(cru_system PUBLIC CRU_EXPORT_API) + +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 new file mode 100644 index 0000000..b91ca69 --- /dev/null +++ b/works/life/operating-system-experiment/Thread.cpp @@ -0,0 +1,67 @@ +#include "Thread.h" + +#include +#include +#include + +namespace cru { +Thread::Thread(Thread &&other) noexcept + : joined_(other.joined_), thread_handle_(other.thread_handle_) { + other.joined_ = false; + other.thread_handle_ = nullptr; +} + +Thread &Thread::operator=(Thread &&other) noexcept { + if (this != &other) { + joined_ = other.joined_; + thread_handle_ = other.thread_handle_; + other.joined_ = false; + other.thread_handle_ = nullptr; + } + + return *this; +} + +Thread::~Thread() { Destroy(); } + +void Thread::Join() { + assert(thread_handle_); + joined_ = true; + WaitForSingleObject(thread_handle_, INFINITE); +} + +void Thread::Detach() { + assert(thread_handle_); + detached_ = true; +} + +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_ && thread_handle_ != nullptr) { + std::terminate(); + } else { + joined_ = false; + thread_handle_ = nullptr; + } +} + +namespace details { +#ifdef CRU_WINDOWS +DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) { + auto p = static_cast *>(lpParameter); + (*p)(); + delete p; + return 0; +} +#else +#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 new file mode 100644 index 0000000..c71c11f --- /dev/null +++ b/works/life/operating-system-experiment/Thread.h @@ -0,0 +1,68 @@ +#ifndef HEADER_THREAD_H +#define HEADER_THREAD_H + +#include "Base.h" + +#ifdef __cplusplus + +#include +#include +#include +#include +#include + +namespace cru { +class CRU_API Thread { +public: + Thread() = default; + template 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(); + + void swap(Thread &other) noexcept; + +private: + void Destroy() noexcept; + +private: + bool detached_ = false; + bool joined_ = false; + +#ifdef CRU_WINDOWS + DWORD thread_id_ = 0; + HANDLE thread_handle_ = nullptr; +#endif +}; + +namespace details { +#ifdef CRU_WINDOWS +CRU_API DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter); +#else +#endif +} // namespace details + +template +Thread::Thread(Fn &&process, Args &&...args) { + std::tuple...> a{std::forward(args)...}; + auto p = new std::function( + [process = std::forward(process), args = std::move(a)]() { + std::apply(process, std::move(args)); + }); + +#ifdef CRU_WINDOWS + thread_handle_ = ::CreateThread(nullptr, 0, &::cru::details::ThreadProc, + static_cast(p), 0, &thread_id_); +#endif +}; +} // namespace cru + +#endif + +#endif diff --git a/works/life/operating-system-experiment/main.cpp b/works/life/operating-system-experiment/main.cpp new file mode 100644 index 0000000..ada8c85 --- /dev/null +++ b/works/life/operating-system-experiment/main.cpp @@ -0,0 +1,16 @@ +#include "Thread.h" + +#include +#include + +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; +} -- cgit v1.2.3