diff --git a/CMakeLists.txt b/CMakeLists.txt index 359c8a51..1cb48acf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,6 @@ list ( ##----------------------------------------------------------------------------- if (LINUX) list (APPEND UTIL_FILES - thread/thread_std.hpp thread/event_futex.cpp thread/flag_futex.cpp rand/system_linux.cpp @@ -174,41 +173,30 @@ endif () ############################################################################### list (APPEND UTIL_FILES - thread/condition_variable.hpp thread/event.hpp thread/flag.hpp - thread/mutex.hpp thread/primitive.hpp thread/semaphore.hpp - thread/thread.hpp ) if (LINUX) list (APPEND UTIL_FILES - thread/condition_variable_std.hpp thread/event_futex.cpp thread/event_futex.hpp thread/semaphore_linux.hpp thread/semaphore_linux.cpp thread/flag_futex.cpp thread/flag_futex.hpp - thread/mutex_std.hpp ) elseif (WIN32) list (APPEND UTIL_FILES - thread/condition_variable_win32.cpp - thread/condition_variable_win32.hpp thread/event_std.cpp thread/event_std.hpp thread/event_win32.cpp - thread/mutex_win32.cpp - thread/mutex_win32.hpp thread/semaphore_win32.hpp thread/semaphore_win32.cpp thread/flag_std.cpp thread/flag_std.hpp - thread/thread_win32.cpp - thread/thread_win32.hpp ) else () message (FATAL_ERROR "Unsupported thread platform") @@ -537,7 +525,6 @@ list ( thread/flag.hpp thread/monitor.cpp thread/monitor.hpp - thread/mutex.hpp thread/ticketlock.cpp thread/ticketlock.hpp thread/spinlock.cpp @@ -740,15 +727,12 @@ if (TESTS) stringid stringcache strongdef - thread/condition_variable thread/event thread/flag thread/monitor - thread/mutex thread/semaphore thread/spinlock thread/ticketlock - thread/thread time/8601 traits tuple/index diff --git a/README.adoc b/README.adoc index a2084d38..3ca9adf0 100644 --- a/README.adoc +++ b/README.adoc @@ -2,7 +2,9 @@ A simple cross-platform C++ utility library. -Supported compilers: >=clang-5.x, >=gcc7.x; specifically, we require cxx17 features such as structured bindings which aren't present in older compilers. No attempt has been made to compile under MSVC. +Supported compilers: >=clang-10.x, >=gcc10.x; specifically, we require cxx17 features such as structured bindings which aren't present in older compilers. No attempt has been made to compile under MSVC. + +MinGW must be compiled with PThreads support so that the std threading API is available. === Environment Variables diff --git a/job/queue.cpp b/job/queue.cpp index 49c20ae6..10ff9f11 100644 --- a/job/queue.cpp +++ b/job/queue.cpp @@ -27,7 +27,7 @@ queue::default_parallelism (void) noexcept LOG_ERROR ("Unable to parse JOB_THREADS. Using the default"); } - return cruft::thread::thread::hardware_concurrency (); + return std::thread::hardware_concurrency (); } @@ -62,7 +62,7 @@ queue::queue (unsigned thread_count, unsigned pool_size): CHECK_GE (m_tasks.finishing.capacity (), thread_count); for (auto &t: m_threads) - t = cruft::thread::thread (&queue::loop, this); + t = std::thread (&queue::loop, this); } diff --git a/job/queue.hpp b/job/queue.hpp index 97aeb00b..9c668f44 100644 --- a/job/queue.hpp +++ b/job/queue.hpp @@ -14,7 +14,6 @@ #include "../thread/flag.hpp" #include "../thread/monitor.hpp" #include "../thread/semaphore.hpp" -#include "../thread/thread.hpp" #include "../thread/ticketlock.hpp" #include "../parallel/queue.hpp" @@ -25,6 +24,7 @@ #include #include #include +#include namespace cruft::job { @@ -201,10 +201,10 @@ namespace cruft::job { thread::semaphore m_pending; - std::vector m_threads; + std::vector m_threads; thread::semaphore m_doomed; - thread::thread m_reaper; + std::thread m_reaper; }; } diff --git a/test/job/queue.cpp b/test/job/queue.cpp index e1245439..dcfd278b 100644 --- a/test/job/queue.cpp +++ b/test/job/queue.cpp @@ -1,11 +1,10 @@ /////////////////////////////////////////////////////////////////////////////// #include "job/queue.hpp" -#include "thread/thread.hpp" #include "tap.hpp" #include - #include +#include /////////////////////////////////////////////////////////////////////////////// @@ -33,7 +32,7 @@ main (void) std::atomic count = 0; { - cruft::job::queue q {cruft::thread::thread::hardware_concurrency (), INNER}; + cruft::job::queue q {std::thread::hardware_concurrency (), INNER}; std::vector cookies; std::generate_n (std::back_inserter (cookies), INNER, [&] () { return q.submit ( diff --git a/test/parallel/queue.cpp b/test/parallel/queue.cpp index efa48b81..8b9cae0e 100644 --- a/test/parallel/queue.cpp +++ b/test/parallel/queue.cpp @@ -1,12 +1,13 @@ #include "parallel/queue.hpp" #include "thread/flag.hpp" #include "thread/semaphore.hpp" -#include "thread/thread.hpp" #include "tap.hpp" #include +#include + static constexpr uint32_t slots = 4; static constexpr int parallelism = 8; @@ -65,8 +66,8 @@ main () // start n consumers, and n producers that fill an array with integers std::vector dst (parallelism * chunk_size); - std::vector consumers; - std::vector producers; + std::vector consumers; + std::vector producers; for (int i = 0; i < parallelism; ++i) { consumers.emplace_back ( diff --git a/test/parallel/stack.cpp b/test/parallel/stack.cpp index d36a5129..e2b2ed44 100644 --- a/test/parallel/stack.cpp +++ b/test/parallel/stack.cpp @@ -1,9 +1,9 @@ #include "thread/flag.hpp" -#include "thread/thread.hpp" #include "parallel/stack.hpp" #include "tap.hpp" +#include int main () @@ -57,8 +57,8 @@ int main () static int constexpr ITERATIONS = 8 * 1024; cruft::parallel::stack store (8); cruft::thread::flag ev; - std::vector contestants; - for (unsigned i = 0; i < cruft::thread::thread::hardware_concurrency () + 1; ++i) + std::vector contestants; + for (unsigned i = 0; i < std::thread::hardware_concurrency () + 1; ++i) contestants.emplace_back (fight, std::ref (store), std::ref (ev), ITERATIONS); ev.notify_all (); diff --git a/test/thread/condition_variable.cpp b/test/thread/condition_variable.cpp deleted file mode 100644 index 483b70ba..00000000 --- a/test/thread/condition_variable.cpp +++ /dev/null @@ -1,4 +0,0 @@ -int main () -{ - -} \ No newline at end of file diff --git a/test/thread/event.cpp b/test/thread/event.cpp index 55b338a9..4253089d 100644 --- a/test/thread/event.cpp +++ b/test/thread/event.cpp @@ -1,9 +1,9 @@ #include "thread/event.hpp" -#include "thread/thread.hpp" #include "tap.hpp" #include +#include int @@ -20,14 +20,14 @@ main () std::atomic val = 0; cruft::thread::event a; - cruft::thread::thread t ([&] () { + std::thread t ([&] () { a.wait (); ++val; }); // block for hopefully long enough to allow the above thread to change // the value of the integer. - cruft::thread::this_thread::sleep_for (std::chrono::milliseconds (100)); + std::this_thread::sleep_for (std::chrono::milliseconds (100)); tap.expect_eq (val, 0, "waiting actually blocks"); diff --git a/test/thread/flag.cpp b/test/thread/flag.cpp index c998f374..47c87e97 100644 --- a/test/thread/flag.cpp +++ b/test/thread/flag.cpp @@ -1,8 +1,9 @@ #include "thread/flag.hpp" -#include "thread/thread.hpp" #include "tap.hpp" +#include + int main () @@ -12,12 +13,12 @@ main () cruft::thread::flag f; std::atomic value = 0; - cruft::thread::thread t1 ([&] () { + std::thread t1 ([&] () { f.wait (); value = 1; }); - cruft::thread::this_thread::sleep_for (std::chrono::milliseconds (100)); + std::this_thread::sleep_for (std::chrono::milliseconds (100)); tap.expect_eq (value, 0, "value hasn't been set during wait"); f.notify_all (); @@ -25,12 +26,12 @@ main () t1.join (); tap.expect_eq (value, 1, "value has been changed after wait"); - cruft::thread::thread t2 ([&] () { + std::thread t2 ([&] () { f.wait (); value = 2; }); - cruft::thread::this_thread::sleep_for (std::chrono::milliseconds (100)); + std::this_thread::sleep_for (std::chrono::milliseconds (100)); tap.expect_eq (value, 2, "second wait didn't appear to block"); t2.join (); @@ -59,13 +60,13 @@ main () } }; - std::vector workers; + std::vector workers; std::generate_n ( std::back_inserter (workers), parallelism, [&, i = 0] () mutable { - return cruft::thread::thread { func, i++ }; + return std::thread { func, i++ }; }); for (auto &t: workers) diff --git a/test/thread/monitor.cpp b/test/thread/monitor.cpp index 0e9e5543..9408a954 100644 --- a/test/thread/monitor.cpp +++ b/test/thread/monitor.cpp @@ -9,11 +9,11 @@ #include "thread/event.hpp" #include "thread/monitor.hpp" #include "thread/semaphore.hpp" -#include "thread/thread.hpp" #include "tap.hpp" #include +#include /////////////////////////////////////////////////////////////////////////////// @@ -49,8 +49,8 @@ main () auto &enter = obj->enter; auto &leave = obj->leave; - cruft::thread::thread t1 ([&] () { obj->inc (); }); - cruft::thread::thread t2 ([&] () { obj->inc (); }); + std::thread t1 ([&] () { obj->inc (); }); + std::thread t2 ([&] () { obj->inc (); }); tap.expect_eq (value, 0, "wrapped class was left initialised"); diff --git a/test/thread/mutex.cpp b/test/thread/mutex.cpp deleted file mode 100644 index cace788f..00000000 --- a/test/thread/mutex.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "tap.hpp" -#include "thread/mutex.hpp" - -int main () -{ - cruft::TAP::logger tap; - - cruft::thread::mutex a; - cruft::thread::mutex b; - (void)a; - (void)b; - - return tap.status (); -} \ No newline at end of file diff --git a/test/thread/semaphore.cpp b/test/thread/semaphore.cpp index d8194c99..24fee205 100644 --- a/test/thread/semaphore.cpp +++ b/test/thread/semaphore.cpp @@ -1,10 +1,11 @@ #include "thread/semaphore.hpp" #include "thread/flag.hpp" -#include "thread/thread.hpp" -#include "thread/mutex.hpp" #include "tap.hpp" +#include +#include + /////////////////////////////////////////////////////////////////////////////// void @@ -35,7 +36,7 @@ main () // the spawned thread attempts to double acquire a semaphore with // only one available and so should get blocked immediately. std::atomic test = 0; - cruft::thread::thread t ([&] () { + std::thread t ([&] () { sem.lock (); sem.lock (); test = 1; @@ -44,7 +45,7 @@ main () // wait until we know the thread should have been blocked. it should // not have touched the 'test' variable at this point. while (sem.value () > 0) - cruft::thread::this_thread::yield (); + std::this_thread::yield (); tap.expect_eq (test, 0, "locking blocks in foreign thread"); @@ -56,9 +57,9 @@ main () } { - const auto parallelism = cruft::thread::thread::hardware_concurrency (); + const auto parallelism = std::thread::hardware_concurrency (); constexpr int iterations = 1 << 16; - std::vector threads; + std::vector threads; cruft::thread::semaphore sem (0); diff --git a/test/thread/spinlock.cpp b/test/thread/spinlock.cpp index 49b915ca..354812fd 100644 --- a/test/thread/spinlock.cpp +++ b/test/thread/spinlock.cpp @@ -8,11 +8,11 @@ #include "thread/flag.hpp" #include "thread/spinlock.hpp" -#include "thread/thread.hpp" #include "tap.hpp" #include +#include /////////////////////////////////////////////////////////////////////////////// @@ -38,14 +38,14 @@ main () l.unlock (); tap.expect (true, "unlocked without contention"); - if (cruft::thread::thread::hardware_concurrency () < 2) { + if (std::thread::hardware_concurrency () < 2) { tap.skip ("n-way fight"); } else { constexpr int iterations = 1 << 12; cruft::thread::flag start_flag; - std::vector contestants; - for (unsigned i = 0; i < cruft::thread::thread::hardware_concurrency (); ++i) + std::vector contestants; + for (unsigned i = 0; i < std::thread::hardware_concurrency (); ++i) contestants.emplace_back (fight, std::ref (start_flag), std::ref (l), iterations); start_flag.notify_all (); @@ -53,7 +53,7 @@ main () for (auto &t: contestants) t.join (); - tap.expect (true, "n-way fight, %! contestants", cruft::thread::thread::hardware_concurrency ()); + tap.expect (true, "n-way fight, %! contestants", std::thread::hardware_concurrency ()); } return tap.status (); diff --git a/test/thread/thread.cpp b/test/thread/thread.cpp deleted file mode 100644 index c0215fc8..00000000 --- a/test/thread/thread.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#include "thread/thread.hpp" -#include "tap.hpp" - -#include - -static void run (std::atomic &val) { ++val; } - - -int main () -{ - cruft::TAP::logger tap; - - // Get the thread to increment an int. If it's been incremented once after - // joining then we assume the thread ran successfully. - std::atomic val = 0; - cruft::thread::thread dude (run, std::ref (val)); - dude.join (); - tap.expect_eq (val.load (), 1, "thread appears to have run"); - - return tap.status (); -} \ No newline at end of file diff --git a/test/thread/ticketlock.cpp b/test/thread/ticketlock.cpp index f9d7abb0..2c1d6ac9 100644 --- a/test/thread/ticketlock.cpp +++ b/test/thread/ticketlock.cpp @@ -8,11 +8,12 @@ #include "thread/flag.hpp" #include "thread/ticketlock.hpp" -#include "thread/thread.hpp" -#include "thread/mutex.hpp" #include "tap.hpp" +#include +#include + /////////////////////////////////////////////////////////////////////////////// using ffs_t = std::chrono::high_resolution_clock; @@ -44,7 +45,7 @@ main () l.unlock (); tap.expect (true, "unlocked without contention"); - if (true || cruft::thread::thread::hardware_concurrency () < 2) { + if (true || std::thread::hardware_concurrency () < 2) { tap.skip ("reasonably fair under contention"); } else { // measure fairness under contention is below some threshold @@ -63,7 +64,7 @@ main () ffs_t::time_point a_finish, b_finish; - cruft::thread::thread a ( + std::thread a ( fight, std::ref (start_flag), std::ref (l), @@ -71,7 +72,7 @@ main () std::ref (a_finish) ); - cruft::thread::thread b ( + std::thread b ( fight, std::ref (start_flag), std::ref (l), diff --git a/thread/condition_variable.hpp b/thread/condition_variable.hpp deleted file mode 100644 index c4c63179..00000000 --- a/thread/condition_variable.hpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#pragma once - -#include "../platform.hpp" - -#if defined(PLATFORM_LINUX) -#include "condition_variable_std.hpp" -#elif defined(PLATFORM_WIN32) -#include "condition_variable_win32.hpp" -#else -#error "Unsupported platform for condition_variable" -#endif \ No newline at end of file diff --git a/thread/condition_variable_std.hpp b/thread/condition_variable_std.hpp deleted file mode 100644 index 2388b9ea..00000000 --- a/thread/condition_variable_std.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#pragma once - -#include - -namespace cruft::thread { - inline namespace std { - using condition_variable = ::std::condition_variable; - } -} \ No newline at end of file diff --git a/thread/condition_variable_win32.cpp b/thread/condition_variable_win32.cpp deleted file mode 100644 index 24db38bc..00000000 --- a/thread/condition_variable_win32.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "condition_variable_win32.hpp" - -#include - -using cruft::thread::win32::condition_variable; - - -/////////////////////////////////////////////////////////////////////////////// -condition_variable::condition_variable () - : m_native (CONDITION_VARIABLE_INIT) -{ - InitializeConditionVariable (&m_native); -} - - -//----------------------------------------------------------------------------- -condition_variable::~condition_variable () -{ ; } - - -/////////////////////////////////////////////////////////////////////////////// -void -condition_variable::wait (std::unique_lock &lock) -{ - SleepConditionVariableCS ( - &m_native, &lock.mutex ()->native_handle (), INFINITE - ); -} - - -/////////////////////////////////////////////////////////////////////////////// -void condition_variable::notify_one (void) noexcept -{ - WakeConditionVariable (&m_native); -} - - -//----------------------------------------------------------------------------- -void condition_variable::notify_all () noexcept -{ - WakeAllConditionVariable (&m_native); -} diff --git a/thread/condition_variable_win32.hpp b/thread/condition_variable_win32.hpp deleted file mode 100644 index f9446468..00000000 --- a/thread/condition_variable_win32.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#pragma once - -#include "mutex.hpp" - -#include - -namespace cruft::thread { - inline namespace win32 { - enum class cv_status { - no_timeout, - timeout - }; - - class condition_variable { - public: - condition_variable (); - condition_variable (condition_variable const&) noexcept = delete; - condition_variable& operator= (condition_variable const&) = delete; - ~condition_variable (); - - void notify_one (void) noexcept; - void notify_all (void) noexcept; - - void wait (std::unique_lock&); - - template - void wait ( - std::unique_lock &lock, - PredicateT pred - ) { - while (!pred ()) - wait (lock); - } - - template - cv_status - wait_for ( - std::unique_lock& lock, - std::chrono::duration const &rel_time - ); - - template - bool wait_for ( - std::unique_lock& lock, - std::chrono::duration const &rel_time, - PredicateT pred - ); - - private: - CONDITION_VARIABLE m_native; - }; - }; -} diff --git a/thread/event_std.hpp b/thread/event_std.hpp index e1be333c..d114fc2e 100644 --- a/thread/event_std.hpp +++ b/thread/event_std.hpp @@ -8,10 +8,9 @@ #pragma once -#include "condition_variable.hpp" -#include "mutex.hpp" - #include +#include +#include namespace cruft::thread { @@ -49,8 +48,8 @@ namespace cruft::thread { private: std::atomic m_value; - mutex m_mutex; - condition_variable m_cv; + std::mutex m_mutex; + std::condition_variable m_cv; }; } diff --git a/thread/flag_std.hpp b/thread/flag_std.hpp index 50199526..2275c092 100644 --- a/thread/flag_std.hpp +++ b/thread/flag_std.hpp @@ -1,40 +1,40 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2018 Danny Robson - */ - -#pragma once - -#include "mutex.hpp" -#include "condition_variable.hpp" - -#include - -namespace cruft::thread { - /// a fire-once event that users can wait upon. if already fired then - /// waiting will be a noop. - class flag { - public: - flag (); - - /// blocks indefinitely until the flag has been set. - void wait (void); - - /// wake one thread waiting on the flag. - /// - /// it may be possible, through spurious wakeups, that more threads - /// are release than requested. though this should not be typical. - void notify_one (void); - - /// wake all threads waiting on the flag - void notify_all (void); - - private: - std::atomic fired; - ::cruft::thread::mutex m_mutex; - ::cruft::thread::condition_variable m_condition; - }; -} +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2018 Danny Robson + */ + +#pragma once + +#include +#include +#include + + +namespace cruft::thread { + /// a fire-once event that users can wait upon. if already fired then + /// waiting will be a noop. + class flag { + public: + flag (); + + /// blocks indefinitely until the flag has been set. + void wait (void); + + /// wake one thread waiting on the flag. + /// + /// it may be possible, through spurious wakeups, that more threads + /// are release than requested. though this should not be typical. + void notify_one (void); + + /// wake all threads waiting on the flag + void notify_all (void); + + private: + std::atomic fired; + std::mutex m_mutex; + std::condition_variable m_condition; + }; +} diff --git a/thread/fwd.hpp b/thread/fwd.hpp deleted file mode 100644 index 920888dc..00000000 --- a/thread/fwd.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -namespace cruft::thread { -} \ No newline at end of file diff --git a/thread/monitor.hpp b/thread/monitor.hpp index 76a939a4..ce72fb59 100644 --- a/thread/monitor.hpp +++ b/thread/monitor.hpp @@ -6,16 +6,15 @@ * Copyright 2018 Danny Robson */ -#ifndef CRUFT_UTIL_THREAD_MONITOR_HPP -#define CRUFT_UTIL_THREAD_MONITOR_HPP +#pragma once -#include "mutex.hpp" - -#include #include +#include +#include + namespace cruft::thread { - template + template class monitor { public: template @@ -48,5 +47,3 @@ namespace cruft::thread { ValueT m_value; }; }; - -#endif diff --git a/thread/mutex.hpp b/thread/mutex.hpp deleted file mode 100644 index d2a66f5d..00000000 --- a/thread/mutex.hpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#pragma once - -#include "../platform.hpp" - -#if defined(PLATFORM_LINUX) -#include "mutex_std.hpp" -#elif defined(PLATFORM_WIN32) -#include "mutex_win32.hpp" -#else -#error "Unsupported mutex platform" -#endif diff --git a/thread/mutex_std.hpp b/thread/mutex_std.hpp deleted file mode 100644 index f5b7e7b7..00000000 --- a/thread/mutex_std.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#pragma once - -#include - -namespace cruft::thread { - inline namespace std { - using mutex = ::std::mutex; - } -} diff --git a/thread/mutex_win32.cpp b/thread/mutex_win32.cpp deleted file mode 100644 index 3c4c69ff..00000000 --- a/thread/mutex_win32.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "mutex.hpp" - -using cruft::thread::win32::mutex; - - -/////////////////////////////////////////////////////////////////////////////// -mutex::~mutex () -{ - DeleteCriticalSection (&m_section); -} - - -/////////////////////////////////////////////////////////////////////////////// -void mutex::lock (void) -{ - EnterCriticalSection (&m_section); -} - - -//----------------------------------------------------------------------------- -void mutex::unlock (void) -{ - LeaveCriticalSection (&m_section); -} - - -//----------------------------------------------------------------------------- -bool mutex::try_lock (void) -{ - return TryEnterCriticalSection (&m_section); -} - - -/////////////////////////////////////////////////////////////////////////////// -CRITICAL_SECTION& -mutex::native_handle (void) -{ - return m_section; -} diff --git a/thread/mutex_win32.hpp b/thread/mutex_win32.hpp deleted file mode 100644 index b161e058..00000000 --- a/thread/mutex_win32.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#pragma once - -#include "../win32/handle.hpp" -#include "../win32/windows.hpp" - -// Include the std mutex header so we can get access to expected -// functionality like std::lock_guard. -#include - -namespace cruft::thread { - inline namespace win32 { - class mutex { - public: - constexpr mutex () noexcept - : m_section {} - { - InitializeCriticalSection (&m_section); - } - - mutex (mutex const&) = delete; - ~mutex (); - - void lock (void); - void unlock (void); - bool try_lock (void); - - CRITICAL_SECTION& native_handle (void); - - private: - CRITICAL_SECTION m_section; - }; - }; -} diff --git a/thread/thread.hpp b/thread/thread.hpp deleted file mode 100644 index 2c51994d..00000000 --- a/thread/thread.hpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#pragma once - -#include "../platform.hpp" - -#if defined(PLATFORM_LINUX) -#include "thread_std.hpp" -#elif defined(PLATFORM_WIN32) -#include "thread_win32.hpp" -#else -#error "Unsupported threading system" -#endif \ No newline at end of file diff --git a/thread/thread_std.hpp b/thread/thread_std.hpp deleted file mode 100644 index dedebc23..00000000 --- a/thread/thread_std.hpp +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#pragma once - -#include - -namespace cruft::thread { - inline namespace std { - using thread = ::std::thread; - namespace this_thread = ::std::this_thread; - } -} \ No newline at end of file diff --git a/thread/thread_win32.cpp b/thread/thread_win32.cpp deleted file mode 100644 index 118c062f..00000000 --- a/thread/thread_win32.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "thread_win32.hpp" - -using cruft::thread::win32::thread; - - -/////////////////////////////////////////////////////////////////////////////// -thread::thread () noexcept -{ ; } - - -//----------------------------------------------------------------------------- -thread::thread (thread &&rhs) noexcept -{ - std::swap (m_handle, rhs.m_handle); -} - - -//----------------------------------------------------------------------------- -thread& -thread::operator= (thread &&rhs) noexcept -{ - std::swap (m_handle, rhs.m_handle); - return *this; -} - - -/////////////////////////////////////////////////////////////////////////////// -void thread::join () -{ - WaitForSingleObject (m_handle, INFINITE); -} - - -/////////////////////////////////////////////////////////////////////////////// -unsigned int thread::hardware_concurrency (void) noexcept -{ - SYSTEM_INFO res; - GetNativeSystemInfo (&res); - return res.dwNumberOfProcessors; -} - - -/////////////////////////////////////////////////////////////////////////////// -void cruft::thread::win32::this_thread::yield (void) noexcept -{ - Sleep (0); -} diff --git a/thread/thread_win32.hpp b/thread/thread_win32.hpp deleted file mode 100644 index a0351277..00000000 --- a/thread/thread_win32.hpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright 2019 Danny Robson - */ - -#pragma once - -#include "../win32/handle.hpp" -#include "../win32/windows.hpp" -#include "../win32/except.hpp" - -#include - -namespace cruft::thread { - inline namespace win32 { - namespace detail { - template - std::decay_t - decay_copy (T&& v) - { - return std::forward(v); - } - - - template - class dispatcher { - public: - dispatcher (FunctionT &&func, ArgsT &&...args) - : m_func (std::forward (func)) - , m_args (std::forward (args)...) - { ; } - - void run (void) - { - return _run ( - std::make_index_sequence {} - ); - } - - private: - template - void _run (std::index_sequence ) - { - std::invoke ( - decay_copy (std::forward (m_func)), - decay_copy (std::forward (std::get (m_args)))... - ); - } - - FunctionT m_func; - std::tuple m_args; - }; - - template - DWORD WINAPI run (LPVOID arg) - { - auto *obj = reinterpret_cast (arg); - - try { - obj->run (); - return 0; - } catch (...) { - delete obj; - throw; - } - } - }; - - struct thread { - using id = ::cruft::win32::handle::native_type; - - thread () noexcept; - thread (thread &&) noexcept; - - template - thread (FunctionT &&func, ArgsT&&...args) - { - using dispatch_t = detail::dispatcher; - - auto data = std::make_unique ( - std::forward (func), - std::forward (args)... - ); - - m_handle.reset ( - CreateThread ( - nullptr, 0, - detail::run, - static_cast (data.get ()), - 0, - nullptr - ) - ); - - if (!m_handle) - throw std::system_error ( - cruft::win32::error::last_code (), - std::generic_category () - ); - - data.release (); - } - - - thread (thread const&) = delete; - - thread& operator= (thread&&) noexcept; - - void join (void); - - static unsigned int hardware_concurrency () noexcept; - - private: - ::cruft::win32::handle m_handle; - }; - - namespace this_thread { - void yield (void) noexcept; - - thread::id get_id (void) noexcept; - - template - void sleep_for ( - std::chrono::duration const& sleep_duration - ) { - auto remain = std::chrono::duration_cast ( - sleep_duration - ).count (); - - while (remain > 0) { - auto const step = cruft::min (remain, INFINITE - 1); - Sleep (remain); - remain -= step; - } - } - - - template - void - sleep_until (std::chrono::time_point const& sleep_time) - { - if (ClockT::is_steady) - return sleep_for (sleep_time - ClockT::now ()); - - for (auto now = ClockT::now (); now < sleep_time; now = ClockT::now ()) - sleep_for (sleep_time - now); - } - - - template - void sleep_until (std::chrono::time_point const& sleep_time); - } - }; -} diff --git a/time_win32.cpp b/time_win32.cpp index 06db7b0b..b31253a6 100644 --- a/time_win32.cpp +++ b/time_win32.cpp @@ -8,13 +8,13 @@ #include "time.hpp" -#include "thread/thread.hpp" - #include +#include + /////////////////////////////////////////////////////////////////////////////// void cruft::sleep (uint64_t ns) { - cruft::thread::this_thread::sleep_for (std::chrono::nanoseconds (ns)); + std::this_thread::sleep_for (std::chrono::nanoseconds (ns)); }