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;
 +}
 | 
