19 #if !FOLLY_HAVE_PTHREAD && _WIN32 20 #include <boost/thread/tss.hpp> 25 #include <condition_variable> 29 #include <shared_mutex> 36 namespace portability {
39 int pthread_attr_init(pthread_attr_t* attr) {
40 if (attr ==
nullptr) {
45 attr->detached =
false;
49 int pthread_attr_setdetachstate(pthread_attr_t* attr,
int state) {
50 if (attr ==
nullptr) {
54 attr->detached = state == PTHREAD_CREATE_DETACHED ?
true :
false;
58 int pthread_attr_setstacksize(pthread_attr_t* attr,
size_t kb) {
59 if (attr ==
nullptr) {
67 namespace pthread_detail {
69 if (handle != INVALID_HANDLE_VALUE && !detached) {
75 int pthread_equal(pthread_t threadA, pthread_t threadB) {
76 if (threadA == threadB) {
85 if (threadA->handle == threadB->handle &&
86 threadA->threadID == threadB->threadID) {
93 thread_local pthread_t current_thread_self;
94 struct pthread_startup_info {
96 void* (*startupFunction)(
void*);
97 void* startupArgument;
100 DWORD internal_pthread_thread_start(
void* arg) {
102 auto startupInfo =
reinterpret_cast<pthread_startup_info*
>(arg);
103 current_thread_self = startupInfo->thread;
104 auto ret = startupInfo->startupFunction(startupInfo->startupArgument);
105 if (
sizeof(
void*) !=
sizeof(DWORD)) {
106 auto tmp =
reinterpret_cast<uintptr_t
>(ret);
108 throw std::out_of_range(
109 "Exit code of the pthread is outside the range representable on Windows");
114 return static_cast<DWORD
>(
reinterpret_cast<uintptr_t
>(ret));
120 const pthread_attr_t* attr,
121 void* (*start_routine)(
void*),
123 if (thread ==
nullptr) {
128 size_t stackSize = attr !=
nullptr ? attr->stackSize : 0;
129 bool detach = attr !=
nullptr ? attr->detached :
false;
133 auto startupInfo =
new pthread_startup_info();
134 startupInfo->startupFunction = start_routine;
135 startupInfo->startupArgument = arg;
136 startupInfo->thread = std::make_shared<pthread_detail::pthread_t>();
139 startupInfo->thread->handle = CreateThread(
142 internal_pthread_thread_start,
145 &startupInfo->thread->threadID);
146 ResumeThread(startupInfo->thread->handle);
149 *thread = std::make_shared<pthread_detail::pthread_t>();
150 (*thread)->detached =
true;
151 (*thread)->handle = startupInfo->thread->handle;
152 (*thread)->threadID = startupInfo->thread->threadID;
154 *thread = startupInfo->thread;
159 pthread_t pthread_self() {
161 if (current_thread_self ==
nullptr) {
162 current_thread_self = std::make_shared<pthread_detail::pthread_t>();
163 current_thread_self->threadID = GetCurrentThreadId();
171 ¤t_thread_self->handle,
172 DUPLICATE_SAME_ACCESS,
177 return current_thread_self;
180 int pthread_join(pthread_t thread,
void** exitCode) {
181 if (thread->detached) {
186 if (WaitForSingleObjectEx(thread->handle, INFINITE,
FALSE) == WAIT_FAILED) {
190 if (exitCode !=
nullptr) {
192 if (!GetExitCodeThread(thread->handle, &e)) {
195 *exitCode =
reinterpret_cast<void*
>(
static_cast<uintptr_t
>(e));
201 HANDLE pthread_getw32threadhandle_np(pthread_t thread) {
202 return thread->handle;
205 DWORD pthread_getw32threadid_np(pthread_t thread) {
206 return thread->threadID;
209 int pthread_setschedparam(
212 const sched_param* param) {
213 if (thread->detached) {
218 auto newPrior = param->sched_priority;
219 if (newPrior > THREAD_PRIORITY_TIME_CRITICAL ||
220 newPrior < THREAD_PRIORITY_IDLE) {
224 if (GetPriorityClass(GetCurrentProcess()) != REALTIME_PRIORITY_CLASS) {
225 if (newPrior > THREAD_PRIORITY_IDLE && newPrior < THREAD_PRIORITY_LOWEST) {
228 newPrior = THREAD_PRIORITY_LOWEST;
230 newPrior < THREAD_PRIORITY_TIME_CRITICAL &&
231 newPrior > THREAD_PRIORITY_HIGHEST) {
233 newPrior = THREAD_PRIORITY_HIGHEST;
236 if (!SetThreadPriority(thread->handle, newPrior)) {
242 int pthread_mutexattr_init(pthread_mutexattr_t* attr) {
243 if (attr ==
nullptr) {
247 attr->type = PTHREAD_MUTEX_DEFAULT;
251 int pthread_mutexattr_destroy(pthread_mutexattr_t* attr) {
252 if (attr ==
nullptr) {
259 int pthread_mutexattr_settype(pthread_mutexattr_t* attr,
int type) {
260 if (attr ==
nullptr) {
264 if (type != PTHREAD_MUTEX_DEFAULT && type != PTHREAD_MUTEX_RECURSIVE) {
272 struct pthread_mutex_t_ {
276 std::timed_mutex timed_mtx;
277 std::recursive_timed_mutex recursive_timed_mtx;
281 pthread_mutex_t_(
int mutex_type) : type(mutex_type) {
283 case PTHREAD_MUTEX_NORMAL:
284 new (&timed_mtx) std::timed_mutex();
286 case PTHREAD_MUTEX_RECURSIVE:
287 new (&recursive_timed_mtx) std::recursive_timed_mutex();
294 case PTHREAD_MUTEX_NORMAL:
295 timed_mtx.~timed_mutex();
297 case PTHREAD_MUTEX_RECURSIVE:
298 recursive_timed_mtx.~recursive_timed_mutex();
305 case PTHREAD_MUTEX_NORMAL:
308 case PTHREAD_MUTEX_RECURSIVE:
309 recursive_timed_mtx.lock();
316 case PTHREAD_MUTEX_NORMAL:
317 return timed_mtx.try_lock();
318 case PTHREAD_MUTEX_RECURSIVE:
319 return recursive_timed_mtx.try_lock();
324 bool timed_try_lock(std::chrono::system_clock::time_point
until) {
326 case PTHREAD_MUTEX_NORMAL:
327 return timed_mtx.try_lock_until(until);
328 case PTHREAD_MUTEX_RECURSIVE:
329 return recursive_timed_mtx.try_lock_until(until);
336 case PTHREAD_MUTEX_NORMAL:
339 case PTHREAD_MUTEX_RECURSIVE:
340 recursive_timed_mtx.unlock();
345 void condition_wait(std::condition_variable_any& cond) {
347 case PTHREAD_MUTEX_NORMAL: {
348 std::unique_lock<std::timed_mutex>
lock(timed_mtx);
352 case PTHREAD_MUTEX_RECURSIVE: {
353 std::unique_lock<std::recursive_timed_mutex>
lock(recursive_timed_mtx);
360 bool condition_timed_wait(
361 std::condition_variable_any& cond,
362 std::chrono::system_clock::time_point until) {
364 case PTHREAD_MUTEX_NORMAL: {
365 std::unique_lock<std::timed_mutex>
lock(timed_mtx);
366 return cond.wait_until(
lock, until) == std::cv_status::no_timeout;
368 case PTHREAD_MUTEX_RECURSIVE: {
369 std::unique_lock<std::recursive_timed_mutex>
lock(recursive_timed_mtx);
370 return cond.wait_until(
lock, until) == std::cv_status::no_timeout;
377 int pthread_mutex_init(
378 pthread_mutex_t*
mutex,
379 const pthread_mutexattr_t* attr) {
380 if (mutex ==
nullptr) {
384 auto type = attr !=
nullptr ? attr->type : PTHREAD_MUTEX_DEFAULT;
385 auto ret =
new pthread_mutex_t_(type);
390 int pthread_mutex_destroy(pthread_mutex_t* mutex) {
391 if (mutex ==
nullptr) {
400 int pthread_mutex_lock(pthread_mutex_t* mutex) {
401 if (mutex ==
nullptr) {
411 int pthread_mutex_trylock(pthread_mutex_t* mutex) {
412 if (mutex ==
nullptr) {
416 if ((*mutex)->try_lock()) {
423 static std::chrono::system_clock::time_point timespec_to_time_point(
425 using time_point = std::chrono::system_clock::time_point;
427 std::chrono::seconds(t->tv_sec) + std::chrono::nanoseconds(t->tv_nsec);
428 return time_point(std::chrono::duration_cast<time_point::duration>(ns));
431 int pthread_mutex_timedlock(
432 pthread_mutex_t* mutex,
433 const timespec* abs_timeout) {
434 if (mutex ==
nullptr || abs_timeout ==
nullptr) {
438 auto time = timespec_to_time_point(abs_timeout);
439 if ((*mutex)->timed_try_lock(
time)) {
446 int pthread_mutex_unlock(pthread_mutex_t* mutex) {
447 if (mutex ==
nullptr) {
457 struct pthread_rwlock_t_ {
458 std::shared_timed_mutex mtx;
459 std::atomic<bool> writing{
false};
462 int pthread_rwlock_init(pthread_rwlock_t* rwlock,
const void* attr) {
463 if (attr !=
nullptr) {
466 if (rwlock ==
nullptr) {
470 *rwlock =
new pthread_rwlock_t_();
474 int pthread_rwlock_destroy(pthread_rwlock_t* rwlock) {
475 if (rwlock ==
nullptr) {
484 int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock) {
485 if (rwlock ==
nullptr) {
489 (*rwlock)->mtx.lock_shared();
493 int pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock) {
494 if (rwlock ==
nullptr) {
498 if ((*rwlock)->mtx.try_lock_shared()) {
505 int pthread_rwlock_timedrdlock(
506 pthread_rwlock_t* rwlock,
507 const timespec* abs_timeout) {
508 if (rwlock ==
nullptr) {
512 auto time = timespec_to_time_point(abs_timeout);
513 if ((*rwlock)->mtx.try_lock_shared_until(
time)) {
520 int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock) {
521 if (rwlock ==
nullptr) {
525 (*rwlock)->mtx.lock();
526 (*rwlock)->writing =
true;
532 int pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock) {
533 if (rwlock ==
nullptr) {
537 if ((*rwlock)->mtx.try_lock()) {
538 (*rwlock)->writing =
true;
545 int pthread_rwlock_timedwrlock(
546 pthread_rwlock_t* rwlock,
547 const timespec* abs_timeout) {
548 if (rwlock ==
nullptr) {
552 auto time = timespec_to_time_point(abs_timeout);
553 if ((*rwlock)->mtx.try_lock_until(
time)) {
554 (*rwlock)->writing =
true;
561 int pthread_rwlock_unlock(pthread_rwlock_t* rwlock) {
562 if (rwlock ==
nullptr) {
569 if ((*rwlock)->writing) {
570 (*rwlock)->mtx.unlock();
574 (void)(*rwlock)->writing.compare_exchange_strong(dump,
false);
576 (*rwlock)->mtx.unlock_shared();
581 struct pthread_cond_t_ {
585 std::condition_variable_any cond;
588 int pthread_cond_init(pthread_cond_t* cond,
const void* attr) {
589 if (attr !=
nullptr) {
592 if (cond ==
nullptr) {
596 *cond =
new pthread_cond_t_();
600 int pthread_cond_destroy(pthread_cond_t* cond) {
601 if (cond ==
nullptr) {
610 int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) {
611 if (cond ==
nullptr || mutex ==
nullptr) {
615 (*mutex)->condition_wait((*cond)->cond);
619 int pthread_cond_timedwait(
620 pthread_cond_t* cond,
621 pthread_mutex_t* mutex,
622 const timespec* abstime) {
623 if (cond ==
nullptr || mutex ==
nullptr || abstime ==
nullptr) {
627 auto time = timespec_to_time_point(abstime);
628 if ((*mutex)->condition_timed_wait((*cond)->cond,
time)) {
635 int pthread_cond_signal(pthread_cond_t* cond) {
636 if (cond ==
nullptr) {
640 (*cond)->cond.notify_one();
644 int pthread_cond_broadcast(pthread_cond_t* cond) {
645 if (cond ==
nullptr) {
649 (*cond)->cond.notify_all();
653 int pthread_key_create(pthread_key_t* key,
void (*destructor)(
void*)) {
655 auto newKey =
new boost::thread_specific_ptr<void>(destructor);
658 }
catch (boost::thread_resource_error) {
663 int pthread_key_delete(pthread_key_t key) {
665 auto realKey =
reinterpret_cast<boost::thread_specific_ptr<void>*
>(key);
668 }
catch (boost::thread_resource_error) {
673 void* pthread_getspecific(pthread_key_t key) {
674 auto realKey =
reinterpret_cast<boost::thread_specific_ptr<void>*
>(key);
676 return realKey->get();
679 int pthread_setspecific(pthread_key_t key,
const void*
value) {
681 auto realKey =
reinterpret_cast<boost::thread_specific_ptr<void>*
>(key);
684 boost::detail::set_tss_data(
686 boost::shared_ptr<boost::detail::tss_cleanup_function>(),
687 const_cast<void*>(value),
690 }
catch (boost::thread_resource_error) {
static constexpr int kb(int kilos)
—— Concurrent Priority Queue Implementation ——
requires E e noexcept(noexcept(s.error(std::move(e))))
FOLLY_ALWAYS_INLINE void assume_unreachable()
auto lock(Synchronized< D, M > &synchronized, Args &&...args)
Until until(Predicate pred=Predicate())
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
std::chrono::nanoseconds time()