CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
critical_section.cpp
Go to the documentation of this file.
1
10
11#include "threads/thread.h"
13
14#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
15#include "errors/fatal.h"
16#include <pthread.h>
17#elif defined(_WIN32) || defined(_WIN64)
18#include <windows.h>
19#undef Yield
20#endif
21
22namespace CppCommon {
23
25
26class CriticalSection::Impl
27{
28public:
29 Impl()
30 {
31#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
32 pthread_mutexattr_t mutex_attribute;
33 int result = pthread_mutexattr_init(&mutex_attribute);
34 if (result != 0)
35 throwex SystemException("Failed to initialize a mutex attribute!", result);
36 result = pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
37 if (result != 0)
38 throwex SystemException("Failed to set a mutex recursive attribute!", result);
39 result = pthread_mutex_init(&_lock, &mutex_attribute);
40 if (result != 0)
41 throwex SystemException("Failed to initialize a mutex!", result);
42 result = pthread_mutexattr_destroy(&mutex_attribute);
43 if (result != 0)
44 throwex SystemException("Failed to destroy a mutex attribute!", result);
45#elif defined(_WIN32) || defined(_WIN64)
46 InitializeCriticalSection(&_lock);
47#endif
48 }
49
50 ~Impl()
51 {
52#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
53 int result = pthread_mutex_destroy(&_lock);
54 if (result != 0)
55 fatality(SystemException("Failed to destroy a mutex!", result));
56#elif defined(_WIN32) || defined(_WIN64)
57 DeleteCriticalSection(&_lock);
58#endif
59 }
60
61 void* native() noexcept
62 {
63 return &_lock;
64 }
65
66 bool TryLock()
67 {
68#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
69 int result = pthread_mutex_trylock(&_lock);
70 if ((result != 0) && (result != EAGAIN) && (result != EBUSY) && (result != EDEADLK))
71 throwex SystemException("Failed to try lock a mutex!", result);
72 return (result == 0);
73#elif defined(_WIN32) || defined(_WIN64)
74 return (TryEnterCriticalSection(&_lock) != 0);
75#endif
76 }
77
78 void Lock()
79 {
80#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
81 int result = pthread_mutex_lock(&_lock);
82 if (result != 0)
83 throwex SystemException("Failed to lock a mutex!", result);
84#elif defined(_WIN32) || defined(_WIN64)
85 EnterCriticalSection(&_lock);
86#endif
87 }
88
89 void Unlock()
90 {
91#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
92 int result = pthread_mutex_unlock(&_lock);
93 if (result != 0)
94 throwex SystemException("Failed to unlock a mutex!", result);
95#elif defined(_WIN32) || defined(_WIN64)
96 LeaveCriticalSection(&_lock);
97#endif
98 }
99
100private:
101#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
102 pthread_mutex_t _lock;
103#elif defined(_WIN32) || defined(_WIN64)
104 CRITICAL_SECTION _lock;
105#endif
106};
107
109
111{
112 // Check implementation storage parameters
113 [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
114 static_assert((StorageSize >= sizeof(Impl)), "CriticalSection::StorageSize must be increased!");
115 static_assert(((StorageAlign % alignof(Impl)) == 0), "CriticalSection::StorageAlign must be adjusted!");
116
117 // Create the implementation instance
118 new(&_storage)Impl();
119}
120
122{
123 // Delete the implementation instance
124 reinterpret_cast<Impl*>(&_storage)->~Impl();
125}
126
127void* CriticalSection::native() noexcept { return impl().native(); }
128
129bool CriticalSection::TryLock() { return impl().TryLock(); }
130
132{
133 // Calculate a finish timestamp
134 Timestamp finish = NanoTimestamp() + timespan;
135
136 // Try to acquire critical section at least one time
137 if (TryLock())
138 return true;
139 else
140 {
141 // Try lock or yield for the given timespan
142 while (NanoTimestamp() < finish)
143 {
144 if (TryLock())
145 return true;
146 else
148 }
149
150 // Failed to acquire critical section
151 return false;
152 }
153}
154
155void CriticalSection::Lock() { impl().Lock(); }
156void CriticalSection::Unlock() { impl().Unlock(); }
157
158} // namespace CppCommon
bool TryLock()
Try to acquire critical section without block.
void Lock()
Acquire critical section with block.
bool TryLockFor(const Timespan &timespan)
Try to acquire critical section for the given timespan.
void Unlock()
Release critical section.
High resolution timestamp.
Definition timestamp.h:272
static void Yield() noexcept
Yield to other threads.
Definition thread.cpp:143
Critical section synchronization primitive definition.
#define throwex
Throw extended exception macro.
Definition exceptions.h:23
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
Definition fatal.h:22
C++ Common project definitions.
Thread definition.
Aligned storage validator definition.