density
C++11 library for paged memory management, function queues, heterogeneous queues and lifo memory management
Public Member Functions | Friends | List of all members
sp_heter_queue< RUNTIME_TYPE, ALLOCATOR_TYPE, PROD_CARDINALITY, CONSUMER_CARDINALITY, BUSY_WAIT_FUNC >::reentrant_put_transaction< ELEMENT_COMPLETE_TYPE > Class Template Reference

#include <sp_heter_queue.h>

Public Member Functions

 reentrant_put_transaction () noexcept=default
 
 reentrant_put_transaction (const reentrant_put_transaction &)=delete
 
reentrant_put_transactionoperator= (const reentrant_put_transaction &)=delete
 
template<typename OTHERTYPE , typename = typename std::enable_if< std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value || std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
 reentrant_put_transaction (reentrant_put_transaction< OTHERTYPE > &&i_source) noexcept
 
template<typename OTHERTYPE , typename = typename std::enable_if< std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value || std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
reentrant_put_transactionoperator= (reentrant_put_transaction< OTHERTYPE > &&i_source) noexcept
 
void * raw_allocate (size_t i_size, size_t i_alignment)
 
template<typename INPUT_ITERATOR >
std::iterator_traits< INPUT_ITERATOR >::value_type * raw_allocate_copy (INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end)
 
template<typename INPUT_RANGE >
auto raw_allocate_copy (const INPUT_RANGE &i_source_range) -> decltype(std::declval< reentrant_put_transaction >().raw_allocate_copy( std::begin(i_source_range), std::end(i_source_range)))
 
void * try_raw_allocate (progress_guarantee i_progress_guarantee, size_t i_size, size_t i_alignment) noexcept
 
template<typename INPUT_ITERATOR >
std::iterator_traits< INPUT_ITERATOR >::value_type * try_raw_allocate_copy (progress_guarantee i_progress_guarantee, INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end) noexcept(std:: is_nothrow_copy_constructible< typename std::iterator_traits< INPUT_ITERATOR >::value_type >::value)
 
template<typename INPUT_RANGE >
auto try_raw_allocate_copy (progress_guarantee i_progress_guarantee, const INPUT_RANGE &i_source_range) noexcept(noexcept(std::declval< reentrant_put_transaction >() .try_raw_allocate_copy( i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))) -> decltype(std::declval< reentrant_put_transaction >().try_raw_allocate_copy( i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))
 
void commit () noexcept
 
void cancel () noexcept
 
bool empty () const noexcept
 
 operator bool () const noexcept
 
sp_heter_queuequeue () const noexcept
 
void * element_ptr () const noexcept
 
ELEMENT_COMPLETE_TYPE & element () const noexcept
 
const RUNTIME_TYPE & complete_type () const noexcept
 
 ~reentrant_put_transaction ()
 
 reentrant_put_transaction (PrivateType, sp_heter_queue *i_queue, const Allocation &i_put) noexcept
 

Friends

template<typename OTHERTYPE >
class reentrant_put_transaction
 
void swap (reentrant_put_transaction &i_first, reentrant_put_transaction &i_second) noexcept
 

Detailed Description

template<typename RUNTIME_TYPE = runtime_type<>, typename ALLOCATOR_TYPE = default_allocator, concurrency_cardinality PROD_CARDINALITY = concurrency_multiple, concurrency_cardinality CONSUMER_CARDINALITY = concurrency_multiple, typename BUSY_WAIT_FUNC = default_busy_wait>
template<typename ELEMENT_COMPLETE_TYPE = void>
class density::sp_heter_queue< RUNTIME_TYPE, ALLOCATOR_TYPE, PROD_CARDINALITY, CONSUMER_CARDINALITY, BUSY_WAIT_FUNC >::reentrant_put_transaction< ELEMENT_COMPLETE_TYPE >

Move-only class template that can be bound to a reentrant put transaction, otherwise it's empty.

Template Parameters
ELEMENT_COMPLETE_TYPEComplete type of elements that can be handled by a transaction, or void. ELEMENT_COMPLETE_TYPE must decay to itself (it can't be cv-qualified).

Reentrant transactional put functions on sp_heter_queue return a non-empty reentrant_put_transaction that can be used to allocate raw memory in the queue, inspect or alter the element while it is still not observable in the queue, and commit or cancel the push.

A reentrant_put_transaction is empty when:

Calling raw_allocate, raw_allocate_copy, commit, cancel, element_ptr, element or complete_type on an empty reentrant_put_transaction triggers undefined behavior.

A void reentrant_put_transaction can be move constructed/assigned from any reentrant_put_transaction. A typed reentrant_put_transaction can be move constructed/assigned only from a reentrant_put_transaction with the same ELEMENT_COMPLETE_TYPE.

Constructor & Destructor Documentation

reentrant_put_transaction ( )
defaultnoexcept

Constructs an empty put transaction

reentrant_put_transaction ( const reentrant_put_transaction< ELEMENT_COMPLETE_TYPE > &  )
delete

Copy construction is not allowed.

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
using SpQueueInt =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
static_assert(
!std::is_copy_constructible<
typename SpQueue::template reentrant_put_transaction<>>::value,
"");
static_assert(
!std::is_copy_constructible<
typename SpQueueInt::template reentrant_put_transaction<>>::value,
"");
reentrant_put_transaction ( reentrant_put_transaction< OTHERTYPE > &&  i_source)
inlinenoexcept

Move constructs a reentrant_put_transaction, transferring the state from the source.

Parameters
i_sourcesource to move from. It is left in a valid but indeterminate state.
using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
auto transaction1 = queue.start_reentrant_push(1);
// move from transaction1 to transaction2
auto transaction2(std::move(transaction1));
assert(transaction1.empty());
assert(transaction2.element() == 1);
// commit transaction2
transaction2.commit();
assert(transaction2.empty());
using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
// reentrant_put_transaction<void> can be move constructed from any reentrant_put_transaction<T>
static_assert(
std::is_constructible<
typename SpQueue::template reentrant_put_transaction<void>,
typename SpQueue::template reentrant_put_transaction<void> &&>::value,
"");
static_assert(
std::is_constructible<
typename SpQueue::template reentrant_put_transaction<void>,
typename SpQueue::template reentrant_put_transaction<int> &&>::value,
"");
// reentrant_put_transaction<T> can be move constructed only from reentrant_put_transaction<T>
static_assert(
!std::is_constructible<
typename SpQueue::template reentrant_put_transaction<int>,
typename SpQueue::template reentrant_put_transaction<void> &&>::value,
"");
static_assert(
!std::is_constructible<
typename SpQueue::template reentrant_put_transaction<int>,
typename SpQueue::template reentrant_put_transaction<float> &&>::value,
"");
static_assert(
std::is_constructible<
typename SpQueue::template reentrant_put_transaction<int>,
typename SpQueue::template reentrant_put_transaction<int> &&>::value,
"");

If this transaction is empty the destructor has no side effects. Otherwise it cancels it.

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
queue.start_reentrant_push(42); /* this transaction is destroyed without being committed,
so it gets canceled automatically. */

Member Function Documentation

reentrant_put_transaction& operator= ( const reentrant_put_transaction< ELEMENT_COMPLETE_TYPE > &  )
delete

Copy assignment is not allowed.

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
using SpQueueInt =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
static_assert(
!std::is_copy_assignable<typename SpQueue::template reentrant_put_transaction<>>::value,
"");
static_assert(
!std::is_copy_assignable<
typename SpQueueInt::template reentrant_put_transaction<>>::value,
"");
reentrant_put_transaction& operator= ( reentrant_put_transaction< OTHERTYPE > &&  i_source)
inlinenoexcept

Move assigns a reentrant_put_transaction, transferring the state from the source.

Parameters
i_sourcesource to move from. It is left in a valid but indeterminate state.
using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
auto transaction1 = queue.start_reentrant_push(1);
typename SpQueue::template reentrant_put_transaction<> transaction2;
transaction2 = queue.start_reentrant_push(1);
transaction2 = std::move(transaction1);
transaction2.commit();
assert(transaction2.empty());
// reentrant_put_transaction<void> can be move assigned from any reentrant_put_transaction<T>
using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
static_assert(
std::is_assignable<
typename SpQueue::template reentrant_put_transaction<void>,
typename SpQueue::template reentrant_put_transaction<void> &&>::value,
"");
static_assert(
std::is_assignable<
typename SpQueue::template reentrant_put_transaction<void>,
typename SpQueue::template reentrant_put_transaction<int> &&>::value,
"");
// reentrant_put_transaction<T> can be move assigned only from reentrant_put_transaction<T>
static_assert(
!std::is_assignable<
typename SpQueue::template reentrant_put_transaction<int>,
typename SpQueue::template reentrant_put_transaction<void> &&>::value,
"");
static_assert(
!std::is_assignable<
typename SpQueue::template reentrant_put_transaction<int>,
typename SpQueue::template reentrant_put_transaction<float> &&>::value,
"");
static_assert(
std::is_assignable<
typename SpQueue::template reentrant_put_transaction<int>,
typename SpQueue::template reentrant_put_transaction<int> &&>::value,
"");
void* raw_allocate ( size_t  i_size,
size_t  i_alignment 
)
inline

Allocates a memory block associated to the element being added in the queue. The block may be allocated contiguously with the elements in the memory pages. If the block does not fit in one page, the block is allocated using non-paged memory services of the allocator.


The block doesn't need to be deallocated, and is guaranteed to be valid until the associated element is destroyed. The initial content of the block is undefined.

Parameters
i_sizesize in bytes of the block to allocate.
i_alignmentalignment of the block to allocate. It must be a non-zero power of 2, and less than or equal to i_size.
Precondition
The behavior is undefined if either:
  • this transaction is empty
  • the alignment is not valid
  • the size is not a multiple of the alignment

Complexity: Unspecified.
Effects on iterators: no iterator is invalidated
Throws: unspecified.
Exception guarantee: strong (in case of exception the function has no observable effects).

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
struct Msg
{
std::chrono::high_resolution_clock::time_point m_time =
std::chrono::high_resolution_clock::now();
size_t m_len = 0;
void * m_data = nullptr;
};
auto post_message = [&queue](const void * i_data, size_t i_len) {
auto transaction = queue.template start_reentrant_emplace<Msg>();
transaction.element().m_len = i_len;
transaction.element().m_data = transaction.raw_allocate(i_len, 1);
memcpy(transaction.element().m_data, i_data, i_len);
assert(
!transaction
.empty()); // a put transaction is not empty if it's bound to an element being put
transaction.commit();
assert(transaction.empty()); // the commit makes the transaction empty
};
auto const start_time = std::chrono::high_resolution_clock::now();
auto consume_all_msgs = [&queue, &start_time] {
while (auto consume = queue.try_start_reentrant_consume())
{
auto const & msg = consume.template element<Msg>();
auto const checksum = compute_checksum(msg.m_data, msg.m_len);
std::cout << "Message with checksum " << checksum << " at ";
std::cout << (msg.m_time - start_time).count() << std::endl;
consume.commit();
}
};
int msg_1 = 42, msg_2 = 567;
post_message(&msg_1, sizeof(msg_1));
post_message(&msg_2, sizeof(msg_2));
consume_all_msgs();
std::iterator_traits<INPUT_ITERATOR>::value_type* raw_allocate_copy ( INPUT_ITERATOR  i_begin,
INPUT_ITERATOR  i_end 
)
inline

Allocates a memory block associated to the element being added in the queue, and copies the content from a range of iterators. The block may be allocated contiguously with the elements in the memory pages. If the block does not fit in one page, the block is allocated using non-paged memory services of the allocator.


The block doesn't need to be deallocated, and is guaranteed to be valid until the associated element is destroyed. The initial content of the block is undefined.

Parameters
i_beginfirst element to be copied
i_endfirst element not to be copied


Requires:

  • INPUT_ITERATOR must satisfy the requirements of InputIterator
  • the value type must be trivially destructible
Precondition
The behavior is undefined if either:
  • this transaction is empty
  • i_end is not reachable from i_begin

Complexity: Unspecified.
Effects on iterators: no iterator is invalidated
Throws: unspecified.
Exception guarantee: strong (in case of exception the function has no observable effects)

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
struct Msg
{
size_t m_len = 0;
char * m_chars = nullptr;
};
auto post_message = [&queue](const char * i_data, size_t i_len) {
auto transaction = queue.template start_reentrant_emplace<Msg>();
transaction.element().m_len = i_len;
transaction.element().m_chars = transaction.raw_allocate_copy(i_data, i_data + i_len);
memcpy(transaction.element().m_chars, i_data, i_len);
transaction.commit();
};
auto raw_allocate_copy ( const INPUT_RANGE &  i_source_range) -> decltype(std::declval<reentrant_put_transaction>().raw_allocate_copy( std::begin(i_source_range), std::end(i_source_range)))
inline

Allocates a memory block associated to the element being added in the queue, and copies the content from a range. The block may be allocated contiguously with the elements in the memory pages. If the block does not fit in one page, the block is allocated using non-paged memory services of the allocator.


The block doesn't need to be deallocated, and is guaranteed to be valid until the associated element is destroyed. The initial content of the block is undefined.

Parameters
i_source_rangeto be copied


Requires:

  • The iterators of the range must satisfy the requirements of InputIterator
  • the value type must be trivially destructible
Precondition
The behavior is undefined if either:
  • this transaction is empty

Complexity: Unspecified.
Effects on iterators: no iterator is invalidated
Throws: unspecified.
Exception guarantee: strong (in case of exception the function has no observable effects).

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
struct Msg
{
char * m_chars = nullptr;
};
auto post_message = [&queue](const std::string & i_string) {
auto transaction = queue.template start_reentrant_emplace<Msg>();
transaction.element().m_chars = transaction.raw_allocate_copy(i_string);
transaction.commit();
};
void* try_raw_allocate ( progress_guarantee  i_progress_guarantee,
size_t  i_size,
size_t  i_alignment 
)
inlinenoexcept

Tries to allocates a memory block associated to the element being added in the queue. The block may be allocated contiguously with the elements in the memory pages. If the block does not fit in one page, the block is allocated using non-paged memory services of the allocator.


The block doesn't need to be deallocated, and is guaranteed to be valid until the associated element is destroyed. The initial content of the block is undefined.


If the operation can't be completed with the specified progress guarantee, this function returns nullptr to indicate a failure, and has no observable effects. This function fails if:

  • a memory allocation is necessary but the allocator can't complete it with the specified progress guarantee. A failure with the blocking progress guarantee indicates an out of memory, but no exception is thrown.
  • there is a contention between threads, and the wait-free progress guarantee is requested
  • the algorithm would perform some non wait-free operations (like page pinning), and the wait-free progress guarantee is requested
Parameters
i_progress_guaranteeprogress guarantee to respect
i_sizesize in bytes of the block to allocate.
i_alignmentalignment of the block to allocate. It must be a non-zero power of 2, and less than or equal to i_size.
Returns
pointer to the allocated storage, or null in case of failure
Precondition
The behavior is undefined if either:
  • this transaction is empty
  • the alignment is not valid
  • the size is not a multiple of the alignment

Complexity: Unspecified.
Effects on iterators: no iterator is invalidated
Throws: nothing.

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
struct Msg
{
std::chrono::high_resolution_clock::time_point m_time =
std::chrono::high_resolution_clock::now();
size_t m_len = 0;
void * m_data = nullptr;
};
auto post_message = [&queue](const void * i_data, size_t i_len) {
if (
auto transaction =
queue.template try_start_reentrant_emplace<Msg>(progress_lock_free))
{
// if we fail to allocate the raw block, we don't commit the put transaction
transaction.element().m_len = i_len;
transaction.element().m_data =
transaction.try_raw_allocate(progress_lock_free, i_len, 1);
if (transaction.element().m_data)
{
memcpy(transaction.element().m_data, i_data, i_len);
assert(
!transaction
.empty()); // a put transaction is not empty if it's bound to an element being put
transaction.commit();
assert(transaction.empty()); // the commit makes the transaction empty
}
}
};
auto const start_time = std::chrono::high_resolution_clock::now();
auto consume_all_msgs = [&queue, &start_time] {
while (auto consume = queue.try_start_consume())
{
auto const & msg = consume.template element<Msg>();
auto const checksum = compute_checksum(msg.m_data, msg.m_len);
std::cout << "Message with checksum " << checksum << " at ";
std::cout << (msg.m_time - start_time).count() << std::endl;
consume.commit();
}
};
int msg_1 = 42, msg_2 = 567;
post_message(&msg_1, sizeof(msg_1));
post_message(&msg_2, sizeof(msg_2));
consume_all_msgs();
std::iterator_traits<INPUT_ITERATOR>::value_type* try_raw_allocate_copy ( progress_guarantee  i_progress_guarantee,
INPUT_ITERATOR  i_begin,
INPUT_ITERATOR  i_end 
)
inlinenoexcept

Tries to allocate a memory block associated to the element being added in the queue, and copies the content from a range of iterators. The block may be allocated contiguously with the elements in the memory pages. If the block does not fit in one page, the block is allocated using non-paged memory services of the allocator.


The block doesn't need to be deallocated, and is guaranteed to be valid until the associated element is destroyed. The initial content of the block is undefined.


If the operation can't be completed with the specified progress guarantee, this function returns nullptr to indicate a failure, and has no observable effects. This function fails if:

  • a memory allocation is necessary but the allocator can't complete it with the specified progress guarantee. A failure with the blocking progress guarantee indicates an out of memory, but no exception is thrown.
  • there is a contention between threads, and the wait-free progress guarantee is requested
  • the algorithm would perform some non wait-free operations (like page pinning), and the wait-free progress guarantee is requested
Parameters
i_progress_guaranteeprogress guarantee to respect
i_beginfirst element to be copied
i_endfirst element not to be copied
Returns
pointer to the allocated array, or null in case of failure


Requires:

  • INPUT_ITERATOR must satisfy the requirements of InputIterator
  • the value type must be trivially destructible
Precondition
The behavior is undefined if either:
  • this transaction is empty
  • i_end is not reachable from i_begin

Complexity: Unspecified.
Effects on iterators: no iterator is invalidated
Throws: what the copy constructor of the element throws (conditionally noexcept)
Exception guarantee: strong (in case of exception the function has no observable effects)

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
struct Msg
{
size_t m_len = 0;
char * m_chars = nullptr;
};
auto post_message = [&queue](const char * i_data, size_t i_len) {
auto transaction = queue.template try_start_reentrant_emplace<Msg>(progress_lock_free);
// if we fail to allocate the raw block, we don't commit the put transaction
transaction.element().m_len = i_len;
transaction.element().m_chars =
transaction.try_raw_allocate_copy(progress_lock_free, i_data, i_data + i_len);
if (transaction.element().m_chars)
{
memcpy(transaction.element().m_chars, i_data, i_len);
transaction.commit();
}
};
auto try_raw_allocate_copy ( progress_guarantee  i_progress_guarantee,
const INPUT_RANGE &  i_source_range 
) -> decltype(std::declval<reentrant_put_transaction>().try_raw_allocate_copy( i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))
inlinenoexcept

Tries to allocate a memory block associated to the element being added in the queue, and copies the content from a range. The block may be allocated contiguously with the elements in the memory pages. If the block does not fit in one page, the block is allocated using non-paged memory services of the allocator.


The block doesn't need to be deallocated, and is guaranteed to be valid until the associated element is destroyed. The initial content of the block is undefined.


If the operation can't be completed with the specified progress guarantee, this function returns nullptr to indicate a failure, and has no observable effects. This function fails if:

  • a memory allocation is necessary but the allocator can't complete it with the specified progress guarantee. A failure with the blocking progress guarantee indicates an out of memory, but no exception is thrown.
  • there is a contention between threads, and the wait-free progress guarantee is requested
  • the algorithm would perform some non wait-free operations (like page pinning), and the wait-free progress guarantee is requested
Parameters
i_progress_guaranteeprogress guarantee to respect
i_source_rangeto be copied
Returns
pointer to the allocated array, or null in case of failure


Requires:

  • The iterators of the range must satisfy the requirements of InputIterator
  • the value type must be trivially destructible
Precondition
The behavior is undefined if either:
  • this transaction is empty

Complexity: Unspecified.
Effects on iterators: no iterator is invalidated
Throws: what the copy constructor of the element throws (conditionally noexcept)
Exception guarantee: strong (in case of exception the function has no observable effects).

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
struct Msg
{
char * m_chars = nullptr;
};
auto post_message = [&queue](const std::string & i_string) {
auto transaction = queue.template try_start_reentrant_emplace<Msg>(progress_lock_free);
// if we fail to allocate the raw block, we don't commit the put transaction
transaction.element().m_chars =
transaction.try_raw_allocate_copy(progress_lock_free, i_string);
if (transaction.element().m_chars)
{
transaction.commit();
}
};
void commit ( )
inlinenoexcept

Makes the effects of the transaction observable. This object becomes empty.

Precondition
The behavior is undefined if either:
  • this transaction is empty

Complexity: Constant.
Effects on iterators: no iterator is invalidated
Throws: Nothing.

void cancel ( )
inlinenoexcept

Cancel the transaction. This object becomes empty.

Precondition
The behavior is undefined if either:
  • this transaction is empty

Complexity: Constant.
Effects on iterators: no iterator is invalidated
Throws: Nothing.

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
// start and cancel a put
assert(queue.empty());
auto put = queue.start_reentrant_push(42);
/* assert(queue.empty()); <- this assert would trigger an undefined behavior, because it would access
the queue during a non-reentrant put transaction. */
assert(!put.empty());
put.cancel();
assert(queue.empty() && put.empty());
// start and commit a put
put = queue.start_reentrant_push(42);
put.commit();
assert(queue.try_start_reentrant_consume().template element<int>() == 42);
bool empty ( ) const
inlinenoexcept

Returns true whether this object does not hold the state of a transaction.

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
typename SpQueue::template reentrant_put_transaction<> transaction;
assert(transaction.empty());
transaction = queue.start_reentrant_push(1);
assert(!transaction.empty());
operator bool ( ) const
inlineexplicitnoexcept

Returns true whether this object is bound to a transaction. Same to !consume_operation::empty.

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
typename SpQueue::template reentrant_put_transaction<> transaction;
assert(!transaction);
transaction = queue.start_reentrant_push(1);
assert(transaction);
sp_heter_queue* queue ( ) const
inlinenoexcept

Returns a pointer to the target queue if a transaction is bound, otherwise returns nullptr

using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
typename SpQueue::template reentrant_put_transaction<> transaction;
assert(transaction.queue() == nullptr);
transaction = queue.start_reentrant_push(1);
assert(transaction.queue() == &queue);
void* element_ptr ( ) const
inlinenoexcept

Returns a pointer to the object being added.
Notes:

  • The object is constructed when the transaction is started, so this function always returns a pointer to a valid object.
Precondition
The behavior is undefined if either:
  • this transaction is empty
using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
int value = 42;
auto put =
queue.start_reentrant_dyn_push_copy(runtime_type<>::make<decltype(value)>(), &value);
assert(*static_cast<int *>(put.element_ptr()) == 42);
std::cout << "Putting an " << put.complete_type().type_info().name() << "..." << std::endl;
put.commit();
auto put_1 = queue.start_reentrant_push(1);
assert(*static_cast<int *>(put_1.element_ptr()) == 1); // this is fine
assert(put_1.element() == 1); // this is better
put_1.commit();
ELEMENT_COMPLETE_TYPE& element ( ) const
inlinenoexcept

Returns a reference to the element being added. This function can be used to modify the element before calling the commit.
Note: An element is observable in the queue only after commit has been called on the reentrant_put_transaction. The element is constructed at the begin of the transaction, so the returned object is always valid.


Requires:

  • ELEMENT_COMPLETE_TYPE must not be void
Precondition
The behavior is undefined if:
  • this transaction is empty
using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
int value = 42;
auto untyped_put =
queue.start_reentrant_dyn_push_copy(runtime_type<>::make<decltype(value)>(), &value);
auto typed_put = queue.start_reentrant_push(42.);
/* typed_put = std::move(untyped_put); <- this would not compile: can't assign an untyped
transaction to a typed transaction */
assert(typed_put.element() == 42.);
const RUNTIME_TYPE& complete_type ( ) const
inlinenoexcept

Returns the type of the object being added.

Precondition
The behavior is undefined if either:
  • this transaction is empty
using SpQueue =
sp_heter_queue<runtime_type<>, default_allocator, PROD_CARDINALITY, CONSUMER_CARDINALITY>;
SpQueue queue;
int value = 42;
auto put =
queue.start_reentrant_dyn_push_copy(runtime_type<>::make<decltype(value)>(), &value);
assert(put.complete_type().template is<int>());
std::cout << "Putting an " << put.complete_type().type_info().name() << "..." << std::endl;

Friends And Related Function Documentation

void swap ( reentrant_put_transaction< ELEMENT_COMPLETE_TYPE > &  i_first,
reentrant_put_transaction< ELEMENT_COMPLETE_TYPE > &  i_second 
)
friend

Swaps two instances of reentrant_put_transaction.


The documentation for this class was generated from the following file: