#pragma once #include #include "bits/algorithm.hfa" #include "bits/locks.hfa" #include "bits/sequence.hfa" #include "invoke.h" #include "time_t.hfa" #include "time.hfa" #include #include "alarm.hfa" /////////////////////////////////////////////////////////////////// //// is_blocking_lock /////////////////////////////////////////////////////////////////// trait is_blocking_lock(dtype L | sized(L)) { void on_notify( L &, struct $thread * ); // For synchronization locks to use when acquiring void on_wait( L & ); // For synchronization locks to use when releasing size_t get_recursion_count( L & ); // to get recursion count for cond lock to reset after waking void set_recursion_count( L &, size_t recursion ); // to set recursion count after getting signalled; }; /////////////////////////////////////////////////////////////////// //// info_thread /////////////////////////////////////////////////////////////////// // the info thread is a wrapper around a thread used // to store extra data for use in the condition variable forall(dtype L | is_blocking_lock(L)) { struct info_thread { inline Seqable; // used to put info_thread on a dl queue (aka sequence) struct $thread * t; // waiting thread uintptr_t info; // shadow field L * lock; // lock that is passed to wait() (if one is passed) bool signalled; // true when signalled and false when timeout wakes thread }; void ?{}( info_thread(L) & this, $thread * t ); void ?{}( info_thread(L) & this, $thread * t, uintptr_t info ); void ^?{}( info_thread(L) & this ); // for use by sequence info_thread(L) *& Back( info_thread(L) * this ); info_thread(L) *& Next( info_thread(L) * this ); } /////////////////////////////////////////////////////////////////// //// Blocking Locks /////////////////////////////////////////////////////////////////// struct blocking_lock { // Spin lock used for mutual exclusion __spinlock_t lock; // List of blocked threads Sequence( $thread ) blocked_threads; // Count of current blocked threads size_t wait_count; // Flag if the lock allows multiple acquisition bool multi_acquisition; // Flag if lock can be released by non owner bool strict_owner; // Current thread owning the lock struct $thread * owner; // Number of recursion level size_t recursion_count; }; struct single_acquisition_lock { inline blocking_lock; }; struct owner_lock { inline blocking_lock; }; struct multiple_acquisition_lock { inline blocking_lock; }; void ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner ); void ^?{}( blocking_lock & this ); void ?{}( single_acquisition_lock & this ); void ^?{}( single_acquisition_lock & this ); void ?{}( owner_lock & this ); void ^?{}( owner_lock & this ); void ?{}( multiple_acquisition_lock & this ); void ^?{}( multiple_acquisition_lock & this ); void lock( blocking_lock & this ); bool try_lock( blocking_lock & this ); void unlock( blocking_lock & this ); void on_notify( blocking_lock & this, struct $thread * t ); void on_wait( blocking_lock & this ); size_t wait_count( blocking_lock & this ); void set_recursion_count( blocking_lock & this, size_t recursion ); size_t get_recursion_count( blocking_lock & this ); void lock( single_acquisition_lock & this ); void unlock( single_acquisition_lock & this ); void on_notify( single_acquisition_lock & this, struct $thread * t ); void on_wait( single_acquisition_lock & this ); void set_recursion_count( single_acquisition_lock & this, size_t recursion ); size_t get_recursion_count( single_acquisition_lock & this ); void lock( owner_lock & this ); void unlock( owner_lock & this ); void on_notify( owner_lock & this, struct $thread * t ); void on_wait( owner_lock & this ); void set_recursion_count( owner_lock & this, size_t recursion ); size_t get_recursion_count( owner_lock & this ); void lock( multiple_acquisition_lock & this ); void unlock( multiple_acquisition_lock & this ); void on_notify( multiple_acquisition_lock & this, struct $thread * t ); void on_wait( multiple_acquisition_lock & this ); void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ); size_t get_recursion_count( multiple_acquisition_lock & this ); /////////////////////////////////////////////////////////////////// //// Synchronization Locks /////////////////////////////////////////////////////////////////// forall(dtype L | is_blocking_lock(L)) { struct condition_variable { // Spin lock used for mutual exclusion __spinlock_t lock; // List of blocked threads Sequence( info_thread(L) ) blocked_threads; // Count of current blocked threads int count; }; void ?{}( condition_variable(L) & this ); void ^?{}( condition_variable(L) & this ); struct alarm_node_wrap { alarm_node_t alarm_node; condition_variable(L) * cond; info_thread(L) * i; }; void ?{}( alarm_node_wrap(L) & this, Time alarm, Duration period, Alarm_Callback callback ); void ^?{}( alarm_node_wrap(L) & this ); void alarm_node_callback( alarm_node_wrap(L) & this ); void alarm_node_wrap_cast( alarm_node_t & a ); bool notify_one( condition_variable(L) & this ); bool notify_all( condition_variable(L) & this ); uintptr_t front( condition_variable(L) & this ); bool empty( condition_variable(L) & this ); int counter( condition_variable(L) & this ); void wait( condition_variable(L) & this ); void wait( condition_variable(L) & this, uintptr_t info ); bool wait( condition_variable(L) & this, Duration duration ); bool wait( condition_variable(L) & this, uintptr_t info, Duration duration ); bool wait( condition_variable(L) & this, Time time ); bool wait( condition_variable(L) & this, uintptr_t info, Time time ); void wait( condition_variable(L) & this, L & l ); void wait( condition_variable(L) & this, L & l, uintptr_t info ); bool wait( condition_variable(L) & this, L & l, Duration duration ); bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ); bool wait( condition_variable(L) & this, L & l, Time time ); bool wait( condition_variable(L) & this, L & l, uintptr_t info, Time time ); }