30# ifdef ZTH_USE_VALGRIND
31# include <valgrind/memcheck.h>
34# if __cplusplus >= 201103L && ZTH_HAVE_EXCEPTIONS
36# define ZTH_FUTURE_EXCEPTION
39# if __cplusplus >= 201703L
45template <
typename Impl,
typename T>
62 Impl
const& impl() const noexcept
64 return static_cast<Impl const&
>(*this);
68template <
typename Impl>
119# if __cplusplus >= 201103L
123 *
this = std::move(p);
129 m_object = p.release();
139 constexpr operator type*()
const noexcept
151 operator bool() const noexcept
153 return get() !=
nullptr;
160template <
typename Impl,
typename T>
166 return *impl().m_object.get();
169 constexpr operator T&()
const noexcept
174 constexpr14 decltype(**
static_cast<T*
>(
nullptr)) operator*()
const
179 constexpr14 decltype(
static_cast<T*
>(
nullptr)->operator->()) operator->() const noexcept
181 return get().operator->();
185 Impl
const& impl() const noexcept
187 return static_cast<Impl const&
>(*this);
191template <
typename Impl>
213 : m_object(p.m_object)
230 m_object = p.m_object;
234# if __cplusplus >= 201103L
237 : m_object(std::move(p))
243 *
this = std::move(p);
248 m_object = std::move(p.m_object);
254 return std::move(m_object);
265 return m_object.
get();
279# if __cplusplus >= 201103L
346 while(!queue_.
empty()) {
377 , m_synchronizer(synchronizer)
392 m_rang = m_synchronizer.
unblock(m_fiber, m_q);
421 return block_(timeout, now, q);
435 return block_(now + timeout, now, q);
455 AlarmClock a(*
this, q, *f, timeout);
464template <
size_t Size = 1>
476# if __cplusplus >= 201103L
484 for(
size_t i = 0; i < Size; i++)
513# if __cplusplus >= 201103L
581# if __cplusplus >= 201103L
588 *
this = std::move(l);
625# if __cplusplus >= 201103L
637 while(m_count < count) {
647 if(m_count > 0 && !m_unblockAll) {
658 if(
unlikely(m_count + count < m_count))
660 m_count = std::numeric_limits<count_type>::max();
673 m_unblockAll =
false;
700# if __cplusplus >= 201103L
742 return wait(now + timeout, now);
745 void signal(
bool queue =
true,
bool queueEveryTime =
false) noexcept
749 if(m_signalled == 0 || queueEveryTime)
794# ifdef ZTH_FUTURE_EXCEPTION
800 operator bool() const noexcept
832# if __cplusplus >= 201103L
856# ifdef ZTH_FUTURE_EXCEPTION
858 Optional(std::exception_ptr exc) noexcept
865 void set(std::exception_ptr exception)
noexcept
868 m_exception = std::move(exception);
882 std::rethrow_exception(m_exception);
885 return *
static_cast<type*
>(p);
893 std::rethrow_exception(m_exception);
895 void const* p = m_data;
896 return *
static_cast<type const*
>(p);
899 std::exception_ptr exception() const noexcept
904# if __cplusplus >= 201103L
910 std::rethrow_exception(m_exception);
913 return std::move(*
static_cast<type*
>(p));
922 return *
static_cast<type*
>(p);
929 void const* p = m_data;
930 return *
static_cast<type const*
>(p);
933# if __cplusplus >= 201103L
939 return std::move(*
static_cast<type*
>(p));
947# ifdef ZTH_USE_VALGRIND
948 VALGRIND_MAKE_MEM_NOACCESS(m_data,
sizeof(m_data));
954# ifdef ZTH_USE_VALGRIND
955 VALGRIND_MAKE_MEM_UNDEFINED(m_data,
sizeof(m_data));
959 void unuse() noexcept
961# ifdef ZTH_FUTURE_EXCEPTION
963 m_exception =
nullptr;
969# ifdef ZTH_USE_VALGRIND
970 VALGRIND_MAKE_MEM_NOACCESS(m_data,
sizeof(m_data));
975 void deinit() noexcept
979# ifdef ZTH_USE_VALGRIND
980 VALGRIND_MAKE_MEM_UNDEFINED(m_data,
sizeof(m_data));
986 alignas(
type)
char m_data[
sizeof(
type)];
988# ifdef ZTH_FUTURE_EXCEPTION
989 std::exception_ptr m_exception;
1007# ifdef ZTH_FUTURE_EXCEPTION
1016# ifdef ZTH_FUTURE_EXCEPTION
1017 m_exception =
nullptr;
1026# ifdef ZTH_FUTURE_EXCEPTION
1027 Optional(std::exception_ptr exc) noexcept
1032 void set(std::exception_ptr exception)
noexcept
1034 m_exception = std::move(exception);
1042 std::rethrow_exception(m_exception);
1045 std::exception_ptr exception() const noexcept
1057# ifdef ZTH_FUTURE_EXCEPTION
1058 std::exception_ptr m_exception;
1067template <
typename T =
void>
1079# if __cplusplus >= 201103L
1089 return m_value.
valid();
1092 operator bool() const noexcept
1116# if __cplusplus >= 201103L
1131# ifdef ZTH_FUTURE_EXCEPTION
1145 std::exception_ptr exception() const noexcept
1147 return m_value.exception();
1154 return m_value.
value();
1167# if __cplusplus >= 201103L
1171 return m_value.
value();
1181 void set_prepare() noexcept
1186 void set_finalize() noexcept
1193 Optional<type> m_value;
1209# if __cplusplus >= 201103L
1219 return m_value.
valid();
1222 operator bool() const noexcept
1240# ifdef ZTH_FUTURE_EXCEPTION
1254 std::exception_ptr exception() const noexcept
1256 return m_value.exception();
1277 void set_prepare() noexcept
1282 void set_finalize() noexcept
1289 Optional<void> m_value;
1298template <
typename T>
1313# if __cplusplus >= 201103L
1324 return m_value.
valid();
1327 operator bool() const noexcept
1345 return valid() && (!m_assigned || m_assigned == assigned);
1357 while(!
valid(assigned))
1381# if __cplusplus >= 201103L
1385 m_value.
set(std::move(value));
1391 put(std::move(value));
1396# ifdef ZTH_FUTURE_EXCEPTION
1404 Mailbox&
operator=(std::exception_ptr value)
1406 put(std::move(value));
1410 std::exception_ptr exception() const noexcept
1412 return m_value.exception();
1424 take_prepare(assigned);
1426# ifdef ZTH_FUTURE_EXCEPTION
1427 std::exception_ptr exc = m_value.exception();
1430 std::rethrow_exception(exc);
1443 m_assigned =
wakeup(item, user, prio);
1460 void put_finalize() noexcept
1471 void take_finalize() noexcept
1479 Optional<type> m_value;
1496# if __cplusplus >= 201103L
1509 if(++m_current >=
count()) {
1510 m_current -=
count();
1535 size_t const m_count;
1556 mutex->p =
static_cast<void*
>(
new zth::Mutex());
1558 }
catch(std::bad_alloc
const&) {
1607 return static_cast<zth::Mutex*
>(mutex->p)->trylock() ? 0 : EBUSY;
1620 static_cast<zth::Mutex*
>(mutex->p)->unlock();
1638 if(value > std::numeric_limits<zth::Semaphore::count_type>::max())
1644 }
catch(std::bad_alloc
const&) {
1677 if(
unlikely(!sem || !sem->p || !value))
1685# define EOVERFLOW EAGAIN
1699 if(
unlikely(s->
value() == std::numeric_limits<size_t>::max()))
1755 }
catch(std::bad_alloc
const&) {
1804 static_cast<zth::Signal*
>(cond->p)->signalAll(
false);
1841 }
catch(std::bad_alloc
const&) {
1862 future->p =
nullptr;
1873 if(
unlikely(!future || !future->p))
1886 if(
unlikely(!future || !future->p))
1905 if(
unlikely(!future || !future->p || !value))
1919 if(
unlikely(!future || !future->p))
1945 gate->p =
static_cast<void*
>(
new zth::Gate(count));
1947 }
catch(std::bad_alloc
const&) {
1967 delete static_cast<zth::Gate*
>(gate->p);
1982 return static_cast<zth::Gate*
>(gate->p)->pass() ? 0 : EBUSY;
1995 static_cast<zth::Gate*
>(gate->p)->wait();
2012 if(
unlikely(!mailbox || mailbox->p))
2018 }
catch(std::bad_alloc
const&) {
2039 mailbox->p =
nullptr;
2050 if(
unlikely(!mailbox || !mailbox->p))
2063 if(
unlikely(!mailbox || !mailbox->p))
2077 if(
unlikely(!mailbox || !mailbox->p))
2093 if(
unlikely(!mailbox || !mailbox->p || !value))
void nap(Timestamp const &sleepUntil=Timestamp::null()) noexcept
Future(cow_string const &name="Future")
Future(cow_string &&name)
virtual ~Future() noexcept override=default
indirection_type operator*()
void set(type &&value) noexcept
void set(type const &value=type()) noexcept
Future & operator=(type &&value) noexcept
Future & operator=(type const &value) noexcept
Future(cow_string &&name)
bool valid() const noexcept
indirection_type operator*() &
virtual ~Future() noexcept override=default
Future(cow_string const &name="Future")
Fiber-aware barrier/gate.
Gate(size_t count, cow_string &&name)
size_t current() const noexcept
virtual ~Gate() noexcept override=default
size_t count() const noexcept
Gate(size_t count, cow_string const &name="Gate")
elem_type::user_type user_type
bool empty() const noexcept
iterator erase(iterator const &pos) noexcept
iterator push_back(elem_type &elem) noexcept
user_type pop_front() noexcept
bool contains(elem_type const &elem) const noexcept
type & front() const noexcept
Mutex RAII, that locks and unlocks the mutex automatically.
Locked(Locked &&l) noexcept
Locked(Locked const &)=delete
Locked & operator=(Locked &&l) noexcept
Locked & operator=(Locked const &)=delete
virtual assigned_type wakeup(Listable &item, queue_type::user_type user, bool prio) noexcept
void put(type const &value)
Mailbox & operator=(type const &value)
Mailbox(cow_string const &name="Mailbox")
bool can_put() const noexcept
virtual ~Mailbox() noexcept override=default
bool can_take() const noexcept
bool valid(assigned_type assigned) const noexcept
virtual void wait(assigned_type assigned)
Mailbox(cow_string &&name)
bool valid() const noexcept
Mailbox & operator=(type &&value)
type take(assigned_type assigned)
virtual void wakeup(Listable &item, queue_type::user_type user, bool prio, size_t q) noexcept final
Mutex(cow_string const &name="Mutex")
bool trylock(Timestamp const &timeout)
virtual ~Mutex() noexcept override=default
virtual char const * id_str() const noexcept override
string const & name() const noexcept
bool valid() const noexcept
Optional(bool set=false) noexcept
bool valid() const noexcept
void set(type &&value) noexcept
Optional(type const &value)
type && value() &&noexcept
Optional(type &&value) noexcept
type const & value() const &noexcept
void set(type const &value=type()) noexcept
Optional & operator=(type &&value) noexcept
Optional & operator=(type const &value) noexcept
Semaphore(count_type init, cow_string &&name)
count_type value() const noexcept
void release(count_type count=1) noexcept
virtual ~Semaphore() noexcept override=default
void acquire(count_type count=1)
Semaphore(count_type init=0, cow_string const &name="Semaphore")
~SharedPointer() noexcept
constexpr SharedPointer(T *object=nullptr) noexcept
constexpr type * get() const noexcept
constexpr type * release() noexcept
constexpr SharedPointer(SharedPointer const &p) noexcept
void reset(T *object=nullptr)
SharedPointer & operator=(T *object)
constexpr SharedPointer & operator=(SharedPointer &&p) noexcept
SharedPointer & operator=(SharedPointer const &p) noexcept
constexpr SharedPointer(SharedPointer &&p) noexcept
constexpr T * operator->() const noexcept
constexpr T & operator*() const noexcept
constexpr SharedReference(SharedPointer_type const &p) noexcept
~SharedReference() noexcept=default
constexpr SharedReference(SharedReference &&p) noexcept
SharedPointer< T > SharedPointer_type
constexpr SharedReference(SharedPointer_type &&p) noexcept
constexpr SharedReference & operator=(SharedReference &&p) noexcept
constexpr SharedReference(type &object) noexcept
SharedReference & operator=(SharedReference const &p) noexcept
constexpr SharedReference() noexcept
constexpr bool valid() const noexcept
constexpr SharedReference(SharedReference const &p) noexcept
SharedPointer_type::type type
constexpr T & get() const noexcept
void signal(bool queue=true, bool queueEveryTime=false) noexcept
void signalAll(bool queue=true) noexcept
Signal(cow_string &&name)
bool wait(TimeInterval const &timeout, Timestamp const &now=Timestamp::now())
Signal(cow_string const &name="Signal")
bool wait(Timestamp const &timeout, Timestamp const &now=Timestamp::now())
virtual ~Signal() noexcept override=default
bool rang() const noexcept
virtual ~AlarmClock() noexcept override=default
virtual bool poll(Timestamp const &now=Timestamp::now()) noexcept override
AlarmClock(SynchronizerBase &synchronizer, size_t q, Fiber &fiber, Timestamp const &timeout) noexcept
queue_type::iterator enqueue(Listable &item, size_t q=0) noexcept
virtual queue_type & queue(size_t q=0)=0
SynchronizerBase(cow_string const &name="Synchronizer")
virtual void wakeup(Listable &item, queue_type::user_type user, bool prio, size_t q) noexcept
Listable * unblockFirst(size_t q=0, bool prio=false) noexcept
bool unblock(Fiber &f, size_t q=0, bool prio=false) noexcept
Unblock the specific fiber.
SynchronizerBase(cow_string &&name)
bool unblockAll(size_t q=0, bool prio=false) noexcept
bool blockFor(TimeInterval const &timeout, Timestamp const &now=Timestamp::now(), size_t q=0)
Block, with timeout.
virtual ~SynchronizerBase() noexcept override
bool blockUntil(Timestamp const &timeout, Timestamp const &now=Timestamp::now(), size_t q=0)
Block, with timeout.
Synchronizer(cow_string &&name)
base::queue_type queue_type
virtual queue_type & queue(size_t q) final
virtual ~Synchronizer() noexcept override
Convenient wrapper around struct timespec that contains a time interval.
constexpr bool isNegative() const noexcept
constexpr bool isNull() const noexcept
virtual bool poll(Timestamp const &now=Timestamp::now()) noexcept override
Timestamp const & timeout() const noexcept
Convenient wrapper around struct timespec that contains an absolute timestamp.
static constexpr Timestamp null() noexcept
friend cow_string str(UniqueIDBase const &)
Keeps track of a process-wide unique ID within the type T.
Fiber & fiber() const noexcept
void scheduleTask(TimedWaitable &w)
void unscheduleTask(TimedWaitable &w)
The class that manages the fibers within this thread.
void release(Fiber &fiber) noexcept
Waiter & waiter() noexcept
Fiber * currentFiber() const noexcept
void add(Fiber *fiber, bool front=false) noexcept
bool schedule(Fiber *preferFiber=nullptr, Timestamp const &now=Timestamp::now())
int zth_cond_broadcast(zth_cond_t *cond) noexcept
Signals all fibers waiting for the condition.
int zth_mailbox_can_take(zth_mailbox_t *mailbox) noexcept
Checks if a mailbox contains data to take.
int zth_future_valid(zth_future_t *future) noexcept
Checks if a future was already set.
int zth_mutex_trylock(zth_mutex_t *mutex) noexcept
Try to lock a mutex.
int zth_gate_pass(zth_gate_t *gate) noexcept
Passes a gate.
int zth_mailbox_init(zth_mailbox_t *mailbox) noexcept
Initializes a mailbox.
int zth_mutex_init(zth_mutex_t *mutex) noexcept
Initializes a mutex.
int zth_cond_signal(zth_cond_t *cond) noexcept
Signals one fiber waiting for the condition.
int zth_gate_init(zth_gate_t *gate, size_t count) noexcept
Initializes a gate.
int zth_cond_wait(zth_cond_t *cond) noexcept
Wait for a condition.
int zth_cond_destroy(zth_cond_t *cond) noexcept
Destroys a condition.
int zth_future_get(zth_future_t *__restrict__ future, uintptr_t *__restrict__ value) noexcept
Wait for and return a future's value.
int zth_gate_wait(zth_gate_t *gate) noexcept
Wait for a gate.
int zth_cond_init(zth_cond_t *cond) noexcept
Initializes a condition.
int zth_sem_post(zth_sem_t *sem) noexcept
Increments a semaphore.
int zth_mutex_lock(zth_mutex_t *mutex) noexcept
Locks a mutex.
int zth_mutex_destroy(zth_mutex_t *mutex) noexcept
Destroys a mutex.
int zth_mailbox_take(zth_mailbox_t *__restrict__ mailbox, uintptr_t *__restrict__ value) noexcept
Wait for and return a mailbox's value.
int zth_future_destroy(zth_future_t *future) noexcept
Destroys a future.
int zth_future_set(zth_future_t *future, uintptr_t value) noexcept
Sets a future and signals all waiting fibers.
int zth_sem_init(zth_sem_t *sem, size_t value) noexcept
Initializes a semaphore.
int zth_mailbox_can_put(zth_mailbox_t *mailbox) noexcept
Checks if a mailbox is empty and can accept data.
int zth_sem_destroy(zth_sem_t *sem) noexcept
Destroys a semaphore.
int zth_sem_trywait(zth_sem_t *sem) noexcept
Try to decrement a semaphore.
int zth_future_wait(zth_future_t *future) noexcept
Wait for a future.
int zth_gate_destroy(zth_gate_t *gate) noexcept
Destroys a gate.
int zth_sem_getvalue(zth_sem_t *__restrict__ sem, size_t *__restrict__ value) noexcept
Returns the value of a semaphore.
int zth_mailbox_put(zth_mailbox_t *mailbox, uintptr_t value) noexcept
Puts a value into the mailbox.
int zth_future_init(zth_future_t *future) noexcept
Initializes a future.
int zth_mailbox_destroy(zth_mailbox_t *mailbox) noexcept
Destroys a mailbox.
int zth_mutex_unlock(zth_mutex_t *mutex) noexcept
Unlock a mutex.
int zth_sem_wait(zth_sem_t *sem) noexcept
Decrements (or wait for) a semaphore.
Worker & currentWorker() noexcept
Return the (thread-local) singleton Worker instance.
void yield(Fiber *preferFiber=nullptr, bool alwaysYield=false, Timestamp const &now=Timestamp::now())
Allow a context switch.
Fiber & currentFiber() noexcept
Return the currently executing fiber.
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
std::basic_string< char, std::char_traits< char >, Config::Allocator< char >::type > string
std::string type using Config::Allocator::type.
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
The configuration of Zth.
Base exception class for Zth exceptions.
Exception thrown when an operation cannot be performed as there is no fiber context.
zth::Future< uintptr_t > zth_future_t_type
zth::Mailbox< uintptr_t > zth_mailbox_t_type
#define ZTH_STRUCTURED_BINDING_FORWARDING_NS(Class)
#define zth_assert(expr)
assert(), but better integrated in Zth.
#define likely(expr)
Marks the given expression to likely be evaluated to true.
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.