1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#define BS_AUTO_MUTEX_NAME mutex
6
7#include <thread>
8#include <chrono>
9#include <mutex>
10#include <condition_variable>
11#include "Threading/BsSpinLock.h"
12
13namespace bs
14{
15 /** @addtogroup Threading
16 * @{
17 */
18
19 /** Returns the number of logical CPU cores. */
20#define BS_THREAD_HARDWARE_CONCURRENCY std::thread::hardware_concurrency()
21
22 /** Returns the ThreadId of the current thread. */
23#define BS_THREAD_CURRENT_ID std::this_thread::get_id()
24
25 /** Causes the current thread to sleep for the provided amount of milliseconds. */
26#define BS_THREAD_SLEEP(ms) std::this_thread::sleep_for(std::chrono::milliseconds(ms));
27
28 /** Wrapper for the C++ std::mutex. */
29 using Mutex = std::mutex;
30
31 /** Wrapper for the C++ std::recursive_mutex. */
32 using RecursiveMutex = std::recursive_mutex;
33
34 /** Wrapper for the C++ std::condition_variable. */
35 using Signal = std::condition_variable;
36
37 /** Wrapper for the C++ std::thread. */
38 using Thread = std::thread;
39
40 /** Wrapper for the C++ std::thread::id. */
41 using ThreadId = std::thread::id;
42
43 /** Wrapper for the C++ std::unique_lock<std::mutex>. */
44 using Lock = std::unique_lock<Mutex>;
45
46 /** Wrapper for the C++ std::unique_lock<std::recursive_mutex>. */
47 using RecursiveLock = std::unique_lock<RecursiveMutex>;
48
49 /** @} */
50
51 /**
52 * Policy that allows the calls its used in to pick between no locking and mutex locking through a template parameter.
53 */
54 template<bool LOCK>
55 class LockingPolicy
56 { };
57
58 /** Scoped lock that provides RAII-style locking and accepts both a normal mutex and a locking policy as input. */
59 template<bool LOCK>
60 class ScopedLock
61 { };
62
63 /** Specialization of LockingPolicy that performs no locking. */
64 template<>
65 class LockingPolicy<false> final
66 {
67 public:
68 LockingPolicy() = default;
69
70 void lock() { };
71 void unlock() { }
72 };
73
74 /** Specialization of LockingPolicy that uses a mutex for locking. */
75 template<>
76 class LockingPolicy<true> final
77 {
78 public:
79 LockingPolicy()
80 :mLock(mMutex, std::defer_lock)
81 { }
82
83 void lock()
84 {
85 mLock.lock();
86 };
87
88 void unlock()
89 {
90 mLock.unlock();
91 }
92
93 private:
94 friend class ScopedLock<true>;
95
96 Mutex mMutex;
97 Lock mLock;
98 };
99
100 /** Scoped lock that performs no locking internally. Can only be used with a LockingPolicy. */
101 template<>
102 class ScopedLock<false>
103 {
104 public:
105 ScopedLock(LockingPolicy<false>& policy)
106 { }
107 };
108
109 /** Scoped lock that automatically locks when created and unlocks when it goes out of scope. */
110 template<>
111 class ScopedLock<true>
112 {
113 public:
114 ScopedLock(LockingPolicy<true>& policy)
115 :mLockGuard(policy.mMutex)
116 { }
117
118 ScopedLock(Mutex& mutex)
119 :mLockGuard(mutex)
120 { }
121
122 private:
123 std::lock_guard<Mutex> mLockGuard;
124 };
125}