[Threading] Add ConditionVariable support.

Swift Concurrency would like to be able to use condition variables.
Add support to the threading packages.

rdar://100236038
This commit is contained in:
Alastair Houghton
2022-09-23 14:45:03 +01:00
parent b1040649f2
commit 4495d63c12
12 changed files with 766 additions and 50 deletions

View File

@@ -1,4 +1,4 @@
//==--- Pthreads.h - Threading abstraction implementation ------ -*-C++ -*-===//
//==--- Linux.h - Threading abstraction implementation --------- -*-C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
@@ -21,6 +21,7 @@
#include <pthread.h>
#include <atomic>
#include <chrono>
#include <optional>
#include "llvm/ADT/Optional.h"
@@ -39,13 +40,13 @@ namespace threading_impl {
swift::threading::fatal(#expr " failed with error %d\n", res_); \
} while (0)
#define SWIFT_LINUXTHREADS_RETURN_TRUE_OR_FALSE(expr) \
#define SWIFT_LINUXTHREADS_RETURN_TRUE_OR_FALSE(falseerr, expr) \
do { \
int res_ = (expr); \
switch (res_) { \
case 0: \
return true; \
case EBUSY: \
case falseerr: \
return false; \
default: \
swift::threading::fatal(#expr " failed with error (%d)\n", res_); \
@@ -93,7 +94,8 @@ inline void mutex_unlock(mutex_handle &handle) {
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_unlock(&handle));
}
inline bool mutex_try_lock(mutex_handle &handle) {
SWIFT_LINUXTHREADS_RETURN_TRUE_OR_FALSE(::pthread_mutex_trylock(&handle));
SWIFT_LINUXTHREADS_RETURN_TRUE_OR_FALSE(EBUSY,
::pthread_mutex_trylock(&handle));
}
inline void mutex_unsafe_lock(mutex_handle &handle) {
@@ -121,7 +123,8 @@ inline void lazy_mutex_unlock(lazy_mutex_handle &handle) {
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_unlock(&handle));
}
inline bool lazy_mutex_try_lock(lazy_mutex_handle &handle) {
SWIFT_LINUXTHREADS_RETURN_TRUE_OR_FALSE(::pthread_mutex_trylock(&handle));
SWIFT_LINUXTHREADS_RETURN_TRUE_OR_FALSE(EBUSY,
::pthread_mutex_trylock(&handle));
}
inline void lazy_mutex_unsafe_lock(lazy_mutex_handle &handle) {
@@ -131,6 +134,55 @@ inline void lazy_mutex_unsafe_unlock(lazy_mutex_handle &handle) {
(void)::pthread_mutex_unlock(&handle);
}
// .. ConditionVariable support ..............................................
struct cond_handle {
::pthread_cond_t condition;
::pthread_mutex_t mutex;
};
inline void cond_init(cond_handle &handle) {
handle.condition = PTHREAD_COND_INITIALIZER;
handle.mutex = PTHREAD_MUTEX_INITIALIZER;
}
inline void cond_destroy(cond_handle &handle) {
SWIFT_LINUXTHREADS_CHECK(::pthread_cond_destroy(&handle.condition));
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_destroy(&handle.mutex));
}
inline void cond_lock(cond_handle &handle) {
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_lock(&handle.mutex));
}
inline void cond_unlock(cond_handle &handle) {
SWIFT_LINUXTHREADS_CHECK(::pthread_mutex_unlock(&handle.mutex));
}
inline void cond_signal(cond_handle &handle) {
SWIFT_LINUXTHREADS_CHECK(::pthread_cond_signal(&handle.condition));
}
inline void cond_broadcast(cond_handle &handle) {
SWIFT_LINUXTHREADS_CHECK(::pthread_cond_broadcast(&handle.condition));
}
inline void cond_wait(cond_handle &handle) {
SWIFT_LINUXTHREADS_CHECK(::pthread_cond_wait(&handle.condition, &handle.mutex));
}
template <class Rep, class Period>
inline bool cond_wait(cond_handle &handle,
std::chrono::duration<Rep, Period> duration) {
auto deadline = std::chrono::time_point_cast<
std::chrono::system_clock::duration>(std::chrono::system_clock::now()
+ duration);
return cond_wait(handle, deadline);
}
inline bool cond_wait(cond_handle &handle,
std::chrono::system_clock::time_point deadline) {
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
deadline.time_since_epoch()).count();
struct ::timespec ts = { ::time_t(ns / 1000000000), long(ns % 1000000000) };
SWIFT_LINUXTHREADS_RETURN_TRUE_OR_FALSE(
ETIMEDOUT,
::pthread_cond_timedwait(&handle.condition, &handle.mutex, &ts)
);
}
// .. Once ...................................................................
struct once_t {