density
C++11 library for paged memory management, function queues, heterogeneous queues and lifo memory management
|
#include <sp_function_queue.h>
Public Types | |
template<typename ELEMENT_COMPLETE_TYPE > | |
using | put_transaction = typename UnderlyingQueue::template put_transaction< ELEMENT_COMPLETE_TYPE > |
template<typename ELEMENT_COMPLETE_TYPE > | |
using | reentrant_put_transaction = typename UnderlyingQueue::template reentrant_put_transaction< ELEMENT_COMPLETE_TYPE > |
using | consume_operation = typename UnderlyingQueue::consume_operation |
using | reentrant_consume_operation = typename UnderlyingQueue::reentrant_consume_operation |
Public Member Functions | |
sp_function_queue () noexcept=default | |
sp_function_queue (sp_function_queue &&i_source) noexcept=default | |
sp_function_queue & | operator= (sp_function_queue &&i_source) noexcept=default |
~sp_function_queue () | |
template<typename ELEMENT_COMPLETE_TYPE > | |
void | push (ELEMENT_COMPLETE_TYPE &&i_source) |
template<typename ELEMENT_COMPLETE_TYPE , typename... CONSTRUCTION_PARAMS> | |
void | emplace (CONSTRUCTION_PARAMS &&...i_construction_params) |
template<typename ELEMENT_TYPE > | |
put_transaction< typename std::decay< ELEMENT_TYPE >::type > | start_push (ELEMENT_TYPE &&i_source) |
template<typename ELEMENT_TYPE , typename... CONSTRUCTION_PARAMS> | |
put_transaction< ELEMENT_TYPE > | start_emplace (CONSTRUCTION_PARAMS &&...i_construction_params) |
template<typename ELEMENT_COMPLETE_TYPE > | |
void | reentrant_push (ELEMENT_COMPLETE_TYPE &&i_source) |
template<typename ELEMENT_COMPLETE_TYPE , typename... CONSTRUCTION_PARAMS> | |
void | reentrant_emplace (CONSTRUCTION_PARAMS &&...i_construction_params) |
template<typename ELEMENT_TYPE > | |
reentrant_put_transaction< typename std::decay< ELEMENT_TYPE >::type > | start_reentrant_push (ELEMENT_TYPE &&i_source) |
template<typename ELEMENT_TYPE , typename... CONSTRUCTION_PARAMS> | |
reentrant_put_transaction< ELEMENT_TYPE > | start_reentrant_emplace (CONSTRUCTION_PARAMS &&...i_construction_params) |
template<typename ELEMENT_COMPLETE_TYPE > | |
bool | try_push (progress_guarantee i_progress_guarantee, ELEMENT_COMPLETE_TYPE &&i_source) noexcept(noexcept(m_queue .try_push( i_progress_guarantee, std::forward< ELEMENT_COMPLETE_TYPE >(i_source)))) |
template<typename ELEMENT_COMPLETE_TYPE , typename... CONSTRUCTION_PARAMS> | |
bool | try_emplace (progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&...i_construction_params) noexcept( noexcept(m_queue.template try_emplace< ELEMENT_COMPLETE_TYPE >( i_progress_guarantee, std::forward< CONSTRUCTION_PARAMS >(i_construction_params)...))) |
template<typename ELEMENT_TYPE > | |
put_transaction< typename std::decay< ELEMENT_TYPE >::type > | try_start_push (progress_guarantee i_progress_guarantee, ELEMENT_TYPE &&i_source) noexcept(noexcept(m_queue .try_start_push( i_progress_guarantee, std::forward< ELEMENT_TYPE >(i_source)))) |
template<typename ELEMENT_TYPE , typename... CONSTRUCTION_PARAMS> | |
put_transaction< ELEMENT_TYPE > | try_start_emplace (progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&...i_construction_params) noexcept(noexcept(m_queue .template try_start_emplace< ELEMENT_TYPE >( i_progress_guarantee, std::forward< ELEMENT_TYPE >( i_construction_params)...))) |
template<typename ELEMENT_COMPLETE_TYPE > | |
bool | try_reentrant_push (progress_guarantee i_progress_guarantee, ELEMENT_COMPLETE_TYPE &&i_source) noexcept(noexcept(m_queue .try_reentrant_push( i_progress_guarantee, std::forward< ELEMENT_COMPLETE_TYPE >(i_source)))) |
template<typename ELEMENT_COMPLETE_TYPE , typename... CONSTRUCTION_PARAMS> | |
bool | try_reentrant_emplace (progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&...i_construction_params) noexcept(noexcept(m_queue .template try_reentrant_emplace< ELEMENT_COMPLETE_TYPE >( i_progress_guarantee, std::forward< CONSTRUCTION_PARAMS >( i_construction_params)...))) |
template<typename ELEMENT_TYPE > | |
reentrant_put_transaction< typename std::decay< ELEMENT_TYPE >::type > | try_start_reentrant_push (progress_guarantee i_progress_guarantee, ELEMENT_TYPE &&i_source) noexcept(noexcept(m_queue .try_start_reentrant_push( i_progress_guarantee, std::forward< ELEMENT_TYPE >(i_source)))) |
template<typename ELEMENT_TYPE , typename... CONSTRUCTION_PARAMS> | |
reentrant_put_transaction< ELEMENT_TYPE > | try_start_reentrant_emplace (progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&...i_construction_params) noexcept(noexcept(m_queue .template try_start_reentrant_emplace< ELEMENT_TYPE >( i_progress_guarantee, std::forward< ELEMENT_TYPE >( i_construction_params)...))) |
std::conditional< std::is_void< RET_VAL >::value, bool, density::optional< RET_VAL > >::type | try_consume (PARAMS...i_params) |
std::conditional< std::is_void< RET_VAL >::value, bool, optional< RET_VAL > >::type | try_consume (consume_operation &i_consume, PARAMS...i_params) |
std::conditional< std::is_void< RET_VAL >::value, bool, density::optional< RET_VAL > >::type | try_reentrant_consume (PARAMS...i_params) |
std::conditional< std::is_void< RET_VAL >::value, bool, optional< RET_VAL > >::type | try_reentrant_consume (reentrant_consume_operation &i_consume, PARAMS...i_params) |
template<function_type_erasure ERASURE_ = ERASURE, typename std::enable_if< ERASURE_!=function_manual_clear >::type * = nullptr> | |
void | clear () noexcept |
bool | empty () noexcept |
Static Public Attributes | |
static constexpr bool | concurrent_puts = PROD_CARDINALITY == concurrency_multiple |
static constexpr bool | concurrent_consumes = CONSUMER_CARDINALITY == concurrency_multiple |
static constexpr bool | concurrent_put_consumes = true |
static constexpr bool | is_seq_cst = true |
Friends | |
void | swap (sp_function_queue &i_first, sp_function_queue &i_second) noexcept |
Heterogeneous FIFO pseudo-container specialized to hold callable objects. sp_function_queue is an adaptor for sp_heter_queue.
sp_function_queue is a concurrent version of function_queue that uses a mix of lock free algorithms and spin locking.
This class is very similar to lf_function_queue, with the difference in multiple-producers mode it uses a spin-locking mutex to synchronize the write to the tail pointer.
Implementation note: In single-producer mode this class template is equivalent to lf_heter_queue, and the busy-wait function is not used.
CALLABLE | Signature required to the callable objects. Must be in the form RET_VAL (PARAMS...) |
ALLOCATOR_TYPE | Allocator type to be used. This type must satisfy the requirements of both UntypedAllocator and PagedAllocator. The default is density::default_allocator. |
ERASURE | Type erasure to use the callable objects. Must be a member of density::function_type_erasure. |
PROD_CARDINALITY | specifies whether multiple threads can do put transactions concurrently. Must be a member of density::concurrency_cardinality. |
CONSUMER_CARDINALITY | specifies whether multiple threads can do consume operations concurrently. Must be a member of density::concurrency_cardinality. |
BUSY_WAIT_FUNC | callable object to be invoked (with an empty parameter list) in the body of the spin lock. The default is density::default_busy_wait, that calls std::this_thread::yield. |
If ERASURE == function_manual_clear, sp_function_queue is not able to destroy the callable objects without invoking them. This produces a performance benefit, but:
Thread safeness: A thread doing put operations and another thread doing consumes don't need to be synchronized. If PROD_CARDINALITY is concurrency_multiple, multiple threads are allowed to put without any synchronization. If CONSUMER_CARDINALITY is concurrency_multiple, multiple threads are allowed to consume without any synchronization.
Exception safeness: Any function of sp_heter_queue is noexcept or provides the strong exception guarantee.
This class template provides all the put functions provided by function_queue, and furthermore it adds the try_ variants, that:
using put_transaction = typename UnderlyingQueue::template put_transaction<ELEMENT_COMPLETE_TYPE> |
Alias to sp_heter_queue::put_transaction.
using reentrant_put_transaction = typename UnderlyingQueue::template reentrant_put_transaction<ELEMENT_COMPLETE_TYPE> |
using consume_operation = typename UnderlyingQueue::consume_operation |
Alias to lf_heter_queue::consume_operation.
using reentrant_consume_operation = typename UnderlyingQueue::reentrant_consume_operation |
|
defaultnoexcept |
Default constructor.
|
defaultnoexcept |
Move constructor.
|
inline |
Destructor
|
defaultnoexcept |
Move assignment.
|
inline |
Adds at the end of the queue a callable object.
See sp_heter_queue::push for a detailed description.
|
inline |
Adds at the end of the queue a callable object of type ELEMENT_COMPLETE_TYPE
, in-place-constructing it from a perfect forwarded parameter pack.
Note: the template argument ELEMENT_COMPLETE_TYPE
can't be deduced from the parameters so it must explicitly specified.
See sp_heter_queue::emplace for a detailed description.
|
inline |
Begins a transaction that appends an element of type ELEMENT_TYPE
, copy-constructing or move-constructing it from the source.
See sp_heter_queue::start_push for a detailed description.
Examples
|
inline |
Begins a transaction that appends an element of a type ELEMENT_TYPE
, in-place-constructing it from a perfect forwarded parameter pack.
See sp_heter_queue::start_emplace for a detailed description.
Examples
|
inline |
Adds at the end of the queue a callable object.
See sp_heter_queue::reentrant_push for a detailed description.
|
inline |
Adds at the end of the queue a callable object of type ELEMENT_COMPLETE_TYPE
, in-place-constructing it from a perfect forwarded parameter pack.
Note: the template argument ELEMENT_COMPLETE_TYPE
can't be deduced from the parameters so it must explicitly specified.
See sp_heter_queue::reentrant_emplace for a detailed description.
|
inline |
Begins a transaction that appends an element of type ELEMENT_TYPE
, copy-constructing or move-constructing it from the source.
See sp_heter_queue::start_reentrant_push for a detailed description.
Examples
|
inline |
Begins a transaction that appends an element of a type ELEMENT_TYPE
, in-place-constructing it from a perfect forwarded parameter pack.
See sp_heter_queue::start_reentrant_emplace for a detailed description.
Examples
|
inlinenoexcept |
Tries to add at the end of the queue a callable object respecting a progress guarantee.
See sp_heter_queue::try_push for a detailed description.
|
inlinenoexcept |
Tries to add at the end of the queue a callable object of type ELEMENT_COMPLETE_TYPE
respecting a progress guarantee, in-place-constructing it from a perfect forwarded parameter pack.
Note: the template argument ELEMENT_COMPLETE_TYPE
can't be deduced from the parameters so it must explicitly specified.
See sp_heter_queue::try_emplace for a detailed description.
|
inlinenoexcept |
Tries to begin a transaction that appends an element of type ELEMENT_TYPE
, copy-constructing or move-constructing it from the source.
See sp_heter_queue::try_start_push for a detailed description.
Examples
|
inlinenoexcept |
Tries to begin a transaction appends an element of a type ELEMENT_TYPE
, in-place-constructing it from a perfect forwarded parameter pack.
See sp_heter_queue::try_start_emplace for a detailed description.
Examples
|
inlinenoexcept |
Tries to add at the end of the queue a callable object.
See sp_heter_queue::try_reentrant_push for a detailed description.
|
inlinenoexcept |
Tries to add at the end of the queue a callable object of type ELEMENT_COMPLETE_TYPE
, in-place-constructing it from a perfect forwarded parameter pack.
Note: the template argument ELEMENT_COMPLETE_TYPE
can't be deduced from the parameters so it must explicitly specified.
See sp_heter_queue::try_reentrant_emplace for a detailed description.
|
inlinenoexcept |
Tries to begin a transaction appends an element of type ELEMENT_TYPE
, copy-constructing or move-constructing it from the source.
See sp_heter_queue::try_start_reentrant_push for a detailed description.
Examples
|
inlinenoexcept |
Tries to begin a transaction appends an element of a type ELEMENT_TYPE
, in-place-constructing it from a perfect forwarded parameter pack.
See sp_heter_queue::try_start_reentrant_emplace for a detailed description.
Examples
|
inline |
If the queue is not empty, invokes the first function object of the queue and then deletes it from the queue. Otherwise no operation is performed.
i_params... | parameters to be forwarded to the function object |
This function is not reentrant: if the callable object accesses in any way this queue, the behavior is undefined. Use sp_function_queue::try_reentrant_consume if you are not sure about what the callable object may do.
Throws: unspecified
Exception guarantee: strong (in case of exception the function has no observable effects).
|
inline |
If the queue is not empty, invokes the first function object of the queue and then deletes it from the queue. Otherwise no operation is performed.
The consume operation is performed using the provided consume_operation object. If the element to consume is in the same page of the last element visited by the provided consume operation, the implementation does not need to pin page. For this reason this overload of try_consume is much faster than the other.
i_consume | object to use for the consume operation |
i_params... | parameters to be forwarded to the function object |
This function is not reentrant: if the callable object accesses in any way this queue, the behavior is undefined. Use sp_function_queue::try_reentrant_consume if you are not sure about what the callable object may do.
Throws: unspecified
Exception guarantee: strong (in case of exception the function has no observable effects).
|
inline |
If the queue is not empty, invokes the first function object of the queue and then deletes it from the queue. Otherwise no operation is performed.
i_params... | parameters to be forwarded to the function object |
This function is reentrant: the callable object can access in any way this queue.
Throws: unspecified
Exception guarantee: strong (in case of exception the function has no observable effects).
|
inline |
If the queue is not empty, invokes the first function object of the queue and then deletes it from the queue. Otherwise no operation is performed.
The consume operation is performed using the provided consume_operation object. If the element to consume is in the same page of the last element visited by the provided consume operation, the implementation does not need to pin page. For this reason this overload of try_reentrant_consume is much faster than the other.
i_consume | object to use for the consume operation |
i_params... | parameters to be forwarded to the function object |
This function is reentrant: the callable object can access in any way this queue.
Throws: unspecified
Exception guarantee: strong (in case of exception the function has no observable effects).
|
inlinenoexcept |
Deletes all the callable objects in the queue. This function is disabled at compile-time if ERASURE is function_manual_clear.
Effects on iterators : all the iterators are invalidated
Throws: nothing
Complexity: linear.
|
inlinenoexcept |
Returns whether this container is empty
|
friend |
Swaps two function queues.
|
static |
Whether multiple threads can do put operations on the same queue without any further synchronization.
|
static |
Whether multiple threads can do consume operations on the same queue without any further synchronization.
|
static |
Whether puts and consumes can be done concurrently without any further synchronization. In any case unsynchronized concurrency is constrained by concurrent_puts and concurrent_consumes.
|
static |
Whether this queue is sequential consistent.