diff options
author | crupest <crupest@outlook.com> | 2021-06-09 21:59:17 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-06-09 21:59:17 +0800 |
commit | d42dfdf4b903763997d47b6e2214c2ce33b9bf8e (patch) | |
tree | 80d3266887b59ac8b7518c8ea3567b8ee05b26cf | |
parent | 33ece81cf15b3cb8d4a005194acc67c3a3e5ad35 (diff) | |
download | crupest-d42dfdf4b903763997d47b6e2214c2ce33b9bf8e.tar.gz crupest-d42dfdf4b903763997d47b6e2214c2ce33b9bf8e.tar.bz2 crupest-d42dfdf4b903763997d47b6e2214c2ce33b9bf8e.zip |
import(life): Add operating system experiement.
-rw-r--r-- | works/life/operating-system-experiment/.gitignore | 5 | ||||
-rw-r--r-- | works/life/operating-system-experiment/Base.h | 22 | ||||
-rw-r--r-- | works/life/operating-system-experiment/CMakeLists.txt | 17 | ||||
-rw-r--r-- | works/life/operating-system-experiment/Thread.cpp | 67 | ||||
-rw-r--r-- | works/life/operating-system-experiment/Thread.h | 68 | ||||
-rw-r--r-- | works/life/operating-system-experiment/main.cpp | 16 |
6 files changed, 195 insertions, 0 deletions
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 <Windows.h>
+#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 <cassert>
+#include <exception>
+#include <utility>
+
+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<std::function<void()> *>(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 <functional>
+#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();
+
+ 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 <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));
+ });
+
+#ifdef CRU_WINDOWS
+ thread_handle_ = ::CreateThread(nullptr, 0, &::cru::details::ThreadProc,
+ static_cast<void *>(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 <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;
+}
|