synchronization

#include <compatibility/hpx/lcos/local/event.hpp>

#include <compatibility/hpx/lcos/local/mutex.hpp>

#include <compatibility/hpx/lcos/local/spinlock_no_backoff.hpp>

#include <compatibility/hpx/lcos/local/counting_semaphore.hpp>

#include <compatibility/hpx/lcos/local/recursive_mutex.hpp>

#include <compatibility/hpx/lcos/local/no_mutex.hpp>

#include <compatibility/hpx/lcos/local/shared_mutex.hpp>

#include <compatibility/hpx/lcos/local/once.hpp>

#include <compatibility/hpx/lcos/local/latch.hpp>

#include <compatibility/hpx/lcos/local/barrier.hpp>

#include <compatibility/hpx/lcos/local/sliding_semaphore.hpp>

#include <compatibility/hpx/lcos/local/condition_variable.hpp>

#include <compatibility/hpx/lcos/local/spinlock_pool.hpp>

#include <compatibility/hpx/lcos/local/spinlock.hpp>

#include <hpx/synchronization/event.hpp>

namespace hpx
namespace lcos
namespace local
class event
#include <event.hpp>

Event semaphores can be used for synchronizing multiple threads that need to wait for an event to occur. When the event occurs, all threads waiting for the event are woken up.

Public Functions

event()

Construct a new event semaphore.

bool occurred()

Check if the event has occurred.

void wait()

Wait for the event to occur.

void set()

Release all threads waiting on this semaphore.

void reset()

Reset the event.

Private Types

typedef lcos::local::spinlock mutex_type

Private Functions

void wait_locked(std::unique_lock<mutex_type> &l)
void set_locked(std::unique_lock<mutex_type> l)

Private Members

mutex_type mtx_

This mutex protects the queue.

local::detail::condition_variable cond_
std::atomic<bool> event_

#include <hpx/synchronization/mutex.hpp>

namespace hpx
namespace lcos
namespace local
class mutex

Subclassed by hpx::lcos::local::timed_mutex

Public Functions

HPX_NON_COPYABLE(mutex)
mutex(char const *const description = "")
~mutex()
void lock(char const *description, error_code &ec = throws)
void lock(error_code &ec = throws)
bool try_lock(char const *description, error_code &ec = throws)
bool try_lock(error_code &ec = throws)
void unlock(error_code &ec = throws)

Protected Types

typedef lcos::local::spinlock mutex_type

Protected Attributes

mutex_type mtx_
threads::thread_id_type owner_id_
detail::condition_variable cond_
class timed_mutex : hpx::lcos::local::mutex

Public Functions

HPX_NON_COPYABLE(timed_mutex)
timed_mutex(char const *const description = "")
~timed_mutex()
bool try_lock_until(util::steady_time_point const &abs_time, char const *description, error_code &ec = throws)
bool try_lock_until(util::steady_time_point const &abs_time, error_code &ec = throws)
bool try_lock_for(util::steady_duration const &rel_time, char const *description, error_code &ec = throws)
bool try_lock_for(util::steady_duration const &rel_time, error_code &ec = throws)
namespace threads

Typedefs

using hpx::threads::thread_id_type = typedef thread_id
using hpx::threads::thread_self = typedef coroutines::detail::coroutine_self

Functions

thread_id_type get_self_id()

The function get_self_id returns the HPX thread id of the current thread (or zero if the current thread is not a HPX thread).

thread_self *get_self_ptr()

The function get_self_ptr returns a pointer to the (OS thread specific) self reference to the current HPX thread.

#include <hpx/synchronization/spinlock_no_backoff.hpp>

namespace hpx
namespace lcos
namespace local
struct spinlock_no_backoff
#include <spinlock_no_backoff.hpp>

boost::mutex-compatible spinlock class

Public Functions

HPX_NON_COPYABLE(spinlock_no_backoff)
spinlock_no_backoff()
~spinlock_no_backoff()
void lock()
bool try_lock()
void unlock()

Private Members

std::uint64_t v_

#include <hpx/synchronization/counting_semaphore.hpp>

namespace hpx
namespace lcos
namespace local

Typedefs

typedef counting_semaphore_var counting_semaphore
template <typename Mutex = hpx::lcos::local::spinlock, int N = 0>
class counting_semaphore_var
#include <counting_semaphore.hpp>

A semaphore is a protected variable (an entity storing a value) or abstract data type (an entity grouping several variables that may or may not be numerical) which constitutes the classic method for restricting access to shared resources, such as shared memory, in a multiprogramming environment. Semaphores exist in many variants, though usually the term refers to a counting semaphore, since a binary semaphore is better known as a mutex. A counting semaphore is a counter for a set of available resources, rather than a locked/unlocked flag of a single resource. It was invented by Edsger Dijkstra. Semaphores are the classic solution to preventing race conditions in the dining philosophers problem, although they do not prevent resource deadlocks.

Counting semaphores can be used for synchronizing multiple threads as well: one thread waiting for several other threads to touch (signal) the semaphore, or several threads waiting for one other thread to touch this semaphore.

Public Functions

counting_semaphore_var(std::int64_t value = N)

Construct a new counting semaphore.

Parameters
  • value: [in] The initial value of the internal semaphore lock count. Normally this value should be zero (which is the default), values greater than zero are equivalent to the same number of signals pre- set, and negative values are equivalent to the same number of waits pre-set.

void wait(std::int64_t count = 1)

Wait for the semaphore to be signaled.

Parameters
  • count: [in] The value by which the internal lock count will be decremented. At the same time this is the minimum value of the lock count at which the thread is not yielded.

bool try_wait(std::int64_t count = 1)

Try to wait for the semaphore to be signaled.

Return
The function returns true if the calling thread was able to acquire the requested amount of credits. The function returns false if not sufficient credits are available at this point in time.
Parameters
  • count: [in] The value by which the internal lock count will be decremented. At the same time this is the minimum value of the lock count at which the thread is not yielded.

void signal(std::int64_t count = 1)

Signal the semaphore.

std::int64_t signal_all()

Private Types

typedef Mutex mutex_type

Private Members

mutex_type mtx_
detail::counting_semaphore sem_

#include <hpx/synchronization/recursive_mutex.hpp>

namespace hpx
namespace lcos
namespace local

Typedefs

using hpx::lcos::local::recursive_mutex = typedef detail::recursive_mutex_impl<>

#include <hpx/synchronization/no_mutex.hpp>

namespace hpx
namespace lcos
namespace local
struct no_mutex

Public Functions

void lock()
bool try_lock()
void unlock()

#include <hpx/synchronization/shared_mutex.hpp>

namespace hpx
namespace lcos
namespace local

Typedefs

typedef detail::shared_mutex shared_mutex

#include <hpx/synchronization/once.hpp>

Defines

HPX_ONCE_INIT
namespace hpx
namespace lcos
namespace local

Functions

template <typename F, typename... Args>
void call_once(once_flag &flag, F &&f, Args&&... args)
struct once_flag

Public Functions

HPX_NON_COPYABLE(once_flag)
once_flag()

Private Members

std::atomic<long> status_
lcos::local::event event_

Friends

template <typename F, typename... Args>
void call_once(once_flag &flag, F &&f, Args&&... args)

#include <hpx/synchronization/latch.hpp>

namespace hpx
namespace lcos
namespace local
class latch
#include <latch.hpp>

Latches are a thread coordination mechanism that allow one or more threads to block until an operation is completed. An individual latch is a singleuse object; once the operation has been completed, the latch cannot be reused.

A latch maintains an internal counter_ that is initialized when the latch is created. Threads may block at a synchronization point waiting for counter_ to be decremented to 0. When counter_ reaches 0, all such blocked threads are released.

Calls to countdown_and_wait() , count_down() , wait() , is_ready(), count_up() , and reset() behave as atomic operations.

Note
A local::latch is not a LCO in the sense that it has no global id and it can’t be triggered using the action (parcel) mechanism. Use lcos::latch instead if this is required. It is just a low level synchronization primitive allowing to synchronize a given number of threads.

Public Functions

HPX_NON_COPYABLE(latch)
latch(std::ptrdiff_t count)

Initialize the latch

Requires: count >= 0. Synchronization: None Postconditions: counter_ == count.

~latch()

Requires: No threads are blocked at the synchronization point.

Note
May be called even if some threads have not yet returned from wait() or count_down_and_wait(), provided that counter_ is 0.
Note
The destructor might not return until all threads have exited wait() or count_down_and_wait().
Note
It is the caller’s responsibility to ensure that no other thread enters wait() after one thread has called the destructor. This may require additional coordination.

void count_down_and_wait()

Decrements counter_ by 1 . Blocks at the synchronization point until counter_ reaches 0.

Requires: counter_ > 0.

Synchronization: Synchronizes with all calls that block on this latch and with all is_ready calls on this latch that return true.

Exceptions
  • Nothing.:

void count_down(std::ptrdiff_t n)

Decrements counter_ by n. Does not block.

Requires: counter_ >= n and n >= 0.

Synchronization: Synchronizes with all calls that block on this latch and with all is_ready calls on this latch that return true .

Exceptions
  • Nothing.:

bool is_ready() const

Returns: counter_ == 0. Does not block.

Exceptions
  • Nothing.:

void wait() const

If counter_ is 0, returns immediately. Otherwise, blocks the calling thread at the synchronization point until counter_ reaches 0.

Exceptions
  • Nothing.:

void abort_all()
void count_up(std::ptrdiff_t n)

Increments counter_ by n. Does not block.

Requires: n >= 0.

Exceptions
  • Nothing.:

void reset(std::ptrdiff_t n)

Reset counter_ to n. Does not block.

Requires: n >= 0.

Exceptions
  • Nothing.:

Protected Attributes

util::cache_line_data<mutex_type> mtx_
util::cache_line_data<local::detail::condition_variable> cond_
std::atomic<std::ptrdiff_t> counter_
bool notified_

Private Types

typedef lcos::local::spinlock mutex_type

#include <hpx/synchronization/channel_mpmc.hpp>

namespace hpx
namespace lcos
namespace local

Typedefs

using hpx::lcos::local::channel_mpmc = typedef bounded_channel<T, hpx::lcos::local::spinlock>
template <typename T, typename Mutex = util::spinlock>
class bounded_channel

Public Functions

bounded_channel(std::size_t size)
bounded_channel(bounded_channel &&rhs)
bounded_channel &operator=(bounded_channel &&rhs)
~bounded_channel()
bool get(T *val = nullptr) const
bool set(T &&t)
std::size_t close()
std::size_t capacity() const

Protected Functions

std::size_t close(std::unique_lock<mutex_type> &l)

Private Types

template<>
using mutex_type = Mutex

Private Functions

bool is_full(std::size_t tail) const
bool is_empty(std::size_t head) const

Private Members

hpx::util::cache_aligned_data<mutex_type> mtx_
hpx::util::cache_aligned_data<std::size_t> head_
hpx::util::cache_aligned_data<std::size_t> tail_
std::size_t size_
std::unique_ptr<T[]> buffer_
bool closed_

#include <hpx/synchronization/channel_spsc.hpp>

namespace hpx
namespace lcos
namespace local
template <typename T>
class channel_spsc

Public Functions

channel_spsc(std::size_t size)
channel_spsc(channel_spsc &&rhs)
channel_spsc &operator=(channel_spsc &&rhs)
~channel_spsc()
bool get(T *val = nullptr) const
bool set(T &&t)
std::size_t close()
std::size_t capacity() const

Private Functions

bool is_full(std::size_t tail) const
bool is_empty(std::size_t head) const

Private Members

hpx::util::cache_aligned_data<std::atomic<std::size_t>> head_
hpx::util::cache_aligned_data<std::atomic<std::size_t>> tail_
std::size_t size_
std::unique_ptr<T[]> buffer_
std::atomic<bool> closed_

#include <hpx/synchronization/barrier.hpp>

namespace hpx
namespace lcos
namespace local
class barrier
#include <barrier.hpp>

A barrier can be used to synchronize a specific number of threads, blocking all of the entering threads until all of the threads have entered the barrier.

Note
A barrier is not a LCO in the sense that it has no global id and it can’t be triggered using the action (parcel) mechanism. It is just a low level synchronization primitive allowing to synchronize a given number of threads.

Public Functions

barrier(std::size_t number_of_threads)
~barrier()
void wait()

The function wait will block the number of entering threads (as given by the constructor parameter number_of_threads), releasing all waiting threads as soon as the last thread entered this function.

void count_up()

The function count_up will increase the number of threads to be waited in wait function.

void reset(std::size_t number_of_threads)

The function reset will reset the number of threads as given by the function parameter number_of_threads. the newer coming threads executing the function wait will be waiting until total_ is equal to barrier_flag. The last thread exiting the wait function will notify the newer threads waiting and the newer threads will get the reset number_of_threads_. The function reset can be executed while previous threads executing waiting after they have been waken up. Thus total_ can not be reset to barrier_flag which will break the comparison condition under the function wait.

Private Types

typedef lcos::local::spinlock mutex_type

Private Members

HPX_STATIC_CONSTEXPR std::size_t hpx::lcos::local::barrier::barrier_flag

=

static_cast<std::size_t>(1) << (CHAR_BIT * sizeof(std::size_t) - 1)

std::size_t number_of_threads_
std::size_t total_
mutex_type mtx_
local::detail::condition_variable cond_

#include <hpx/synchronization/sliding_semaphore.hpp>

namespace hpx
namespace lcos
namespace local

Typedefs

typedef sliding_semaphore_var sliding_semaphore
template <typename Mutex = hpx::lcos::local::spinlock>
class sliding_semaphore_var
#include <sliding_semaphore.hpp>

A semaphore is a protected variable (an entity storing a value) or abstract data type (an entity grouping several variables that may or may not be numerical) which constitutes the classic method for restricting access to shared resources, such as shared memory, in a multiprogramming environment. Semaphores exist in many variants, though usually the term refers to a counting semaphore, since a binary semaphore is better known as a mutex. A counting semaphore is a counter for a set of available resources, rather than a locked/unlocked flag of a single resource. It was invented by Edsger Dijkstra. Semaphores are the classic solution to preventing race conditions in the dining philosophers problem, although they do not prevent resource deadlocks.

Sliding semaphores can be used for synchronizing multiple threads as well: one thread waiting for several other threads to touch (signal) the semaphore, or several threads waiting for one other thread to touch this semaphore. The difference to a counting semaphore is that a sliding semaphore will not limit the number of threads which are allowed to proceed, but will make sure that the difference between the (arbitrary) number passed to set and wait does not exceed a given threshold.

Public Functions

sliding_semaphore_var(std::int64_t max_difference, std::int64_t lower_limit = 0)

Construct a new sliding semaphore.

Parameters
  • max_difference: [in] The max difference between the upper limit (as set by wait()) and the lower limit (as set by signal()) which is allowed without suspending any thread calling wait().
  • lower_limit: [in] The initial lower limit.

void set_max_difference(std::int64_t max_difference, std::int64_t lower_limit = 0)

Set/Change the difference that will cause the semaphore to trigger.

Parameters
  • max_difference: [in] The max difference between the upper limit (as set by wait()) and the lower limit (as set by signal()) which is allowed without suspending any thread calling wait().
  • lower_limit: [in] The initial lower limit.

void wait(std::int64_t upper_limit)

Wait for the semaphore to be signaled.

Parameters
  • upper_limit: [in] The new upper limit. The calling thread will be suspended if the difference between this value and the largest lower_limit which was set by signal() is larger than the max_difference.

bool try_wait(std::int64_t upper_limit = 1)

Try to wait for the semaphore to be signaled.

Return
The function returns true if the calling thread would not block if it was calling wait().
Parameters
  • upper_limit: [in] The new upper limit. The calling thread will be suspended if the difference between this value and the largest lower_limit which was set by signal() is larger than the max_difference.

void signal(std::int64_t lower_limit)

Signal the semaphore.

Parameters
  • lower_limit: [in] The new lower limit. This will update the current lower limit of this semaphore. It will also re-schedule all suspended threads for which their associated upper limit is not larger than the lower limit plus the max_difference.

std::int64_t signal_all()

Private Types

typedef Mutex mutex_type

Private Members

mutex_type mtx_
detail::sliding_semaphore sem_

#include <hpx/synchronization/condition_variable.hpp>

namespace hpx
namespace lcos
namespace local

Enums

enum cv_status

Values:

no_timeout
timeout
error
class condition_variable

Public Functions

void notify_one(error_code &ec = throws)
void notify_all(error_code &ec = throws)
void wait(std::unique_lock<mutex> &lock, error_code &ec = throws)
template <class Predicate>
void wait(std::unique_lock<mutex> &lock, Predicate pred, error_code& = throws)
cv_status wait_until(std::unique_lock<mutex> &lock, util::steady_time_point const &abs_time, error_code &ec = throws)
template <typename Predicate>
bool wait_until(std::unique_lock<mutex> &lock, util::steady_time_point const &abs_time, Predicate pred, error_code &ec = throws)
cv_status wait_for(std::unique_lock<mutex> &lock, util::steady_duration const &rel_time, error_code &ec = throws)
template <typename Predicate>
bool wait_for(std::unique_lock<mutex> &lock, util::steady_duration const &rel_time, Predicate pred, error_code &ec = throws)

Private Types

typedef lcos::local::spinlock mutex_type

Private Members

util::cache_line_data<mutex_type> mtx_
util::cache_line_data<detail::condition_variable> cond_
class condition_variable_any

Public Functions

void notify_one(error_code &ec = throws)
void notify_all(error_code &ec = throws)
template <class Lock>
void wait(Lock &lock, error_code &ec = throws)
template <class Lock, class Predicate>
void wait(Lock &lock, Predicate pred, error_code &ec = throws)
template <typename Lock>
cv_status wait_until(Lock &lock, util::steady_time_point const &abs_time, error_code &ec = throws)
template <typename Lock, typename Predicate>
bool wait_until(Lock &lock, util::steady_time_point const &abs_time, Predicate pred, error_code &ec = throws)
template <typename Lock>
cv_status wait_for(Lock &lock, util::steady_duration const &rel_time, error_code &ec = throws)
template <typename Lock, typename Predicate>
bool wait_for(Lock &lock, util::steady_duration const &rel_time, Predicate pred, error_code &ec = throws)

Private Types

typedef lcos::local::spinlock mutex_type

Private Members

util::cache_line_data<mutex_type> mtx_
util::cache_line_data<detail::condition_variable> cond_

#include <hpx/synchronization/spinlock_pool.hpp>

namespace hpx
namespace lcos
namespace local
template <typename Tag, std::size_t N = HPX_HAVE_SPINLOCK_POOL_NUM>
class spinlock_pool

Public Static Functions

static lcos::local::spinlock &spinlock_for(void const *pv)

Private Static Attributes

util::cache_aligned_data<lcos::local::spinlock> pool_
class scoped_lock

Public Functions

template<>
HPX_NON_COPYABLE(scoped_lock)
template<>
scoped_lock(void const *pv)
template<>
~scoped_lock()
template<>
void lock()
template<>
void unlock()

Private Members

template<>
hpx::lcos::local::spinlock &sp_

#include <hpx/synchronization/channel_mpsc.hpp>

namespace hpx
namespace lcos
namespace local

Typedefs

using hpx::lcos::local::channel_mpsc = typedef base_channel_mpsc<T, hpx::lcos::local::spinlock>
template <typename T, typename Mutex = util::spinlock>
class base_channel_mpsc

Public Functions

base_channel_mpsc(std::size_t size)
base_channel_mpsc(base_channel_mpsc &&rhs)
base_channel_mpsc &operator=(base_channel_mpsc &&rhs)
~base_channel_mpsc()
bool get(T *val = nullptr) const
bool set(T &&t)
std::size_t close()
std::size_t capacity() const

Private Types

template<>
using mutex_type = Mutex

Private Functions

bool is_full(std::size_t tail) const
bool is_empty(std::size_t head) const

Private Members

hpx::util::cache_aligned_data<std::atomic<std::size_t>> head_
hpx::util::cache_aligned_data<tail_data> tail_
std::size_t size_
std::unique_ptr<T[]> buffer_
std::atomic<bool> closed_
struct tail_data

Public Members

template<>
mutex_type mtx_
template<>
std::atomic<std::size_t> tail_

#include <hpx/synchronization/spinlock.hpp>

namespace hpx
namespace lcos
namespace local
struct spinlock

Public Functions

HPX_NON_COPYABLE(spinlock)
spinlock(char const *const desc = "hpx::lcos::local::spinlock")
~spinlock()
void lock()
bool try_lock()
void unlock()

Private Functions

bool acquire_lock()
void relinquish_lock()

Private Members

std::uint64_t v_