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

#include <lf_heter_queue.h>

Public Member Functions

 put_transaction () noexcept=default
 
 put_transaction (const put_transaction &)=delete
 
put_transactionoperator= (const 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>
 put_transaction (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>
put_transactionoperator= (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< 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< put_transaction >() .try_raw_allocate_copy( i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))) -> decltype(std::declval< 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
 
lf_heter_queuequeue () const noexcept
 
void * element_ptr () const noexcept
 
ELEMENT_COMPLETE_TYPE & element () const noexcept
 
const RUNTIME_TYPE & complete_type () const noexcept
 
 ~put_transaction ()
 
 put_transaction (PrivateType, lf_heter_queue *i_queue, const Allocation &i_put) noexcept
 

Friends

template<typename OTHERTYPE >
class put_transaction
 
void swap (put_transaction &i_first, 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, consistency_model CONSISTENCY_MODEL = consistency_sequential>
template<typename ELEMENT_COMPLETE_TYPE = void>
class density::lf_heter_queue< RUNTIME_TYPE, ALLOCATOR_TYPE, PROD_CARDINALITY, CONSUMER_CARDINALITY, CONSISTENCY_MODEL >::put_transaction< ELEMENT_COMPLETE_TYPE >

Move-only class template that can be bound to a 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).

Transactional put functions on lf_heter_queue return a non-empty 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 put_transaction is empty when:

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

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

Constructor & Destructor Documentation

put_transaction ( )
defaultnoexcept

Constructs an empty put transaction

put_transaction ( const put_transaction< ELEMENT_COMPLETE_TYPE > &  )
delete

Copy construction is not allowed.

using LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
static_assert(
!std::is_copy_constructible<typename LfQueue::template put_transaction<>>::value, "");
put_transaction ( put_transaction< OTHERTYPE > &&  i_source)
inlinenoexcept

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

Parameters
i_sourcesource to move from. It is left in a valid but indeterminate state.
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>
auto transaction1 = queue.start_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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
// put_transaction<void> can be move constructed from any put_transaction<T>
static_assert(
std::is_constructible<
typename LfQueue::template put_transaction<void>,
typename LfQueue::template put_transaction<void> &&>::value,
"");
static_assert(
std::is_constructible<
typename LfQueue::template put_transaction<void>,
typename LfQueue::template put_transaction<int> &&>::value,
"");
// put_transaction<T> can be move constructed only from put_transaction<T>
static_assert(
!std::is_constructible<
typename LfQueue::template put_transaction<int>,
typename LfQueue::template put_transaction<void> &&>::value,
"");
static_assert(
!std::is_constructible<
typename LfQueue::template put_transaction<int>,
typename LfQueue::template put_transaction<float> &&>::value,
"");
static_assert(
std::is_constructible<
typename LfQueue::template put_transaction<int>,
typename LfQueue::template put_transaction<int> &&>::value,
"");
~put_transaction ( )
inline

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

using LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue queue;
queue.start_push(42); /* this transaction is destroyed without being committed,
so it gets canceled automatically. */

Member Function Documentation

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

Copy assignment is not allowed.

using LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
static_assert(
!std::is_copy_assignable<typename LfQueue::template put_transaction<>>::value, "");
put_transaction& operator= ( put_transaction< OTHERTYPE > &&  i_source)
inlinenoexcept

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

Parameters
i_sourcesource to move from. It is left in a valid but indeterminate state.
using LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue queue;
auto transaction1 = queue.start_push(1);
typename LfQueue::template put_transaction<> transaction2;
transaction2 = std::move(transaction1);
assert(transaction1.empty());
transaction2.commit();
assert(transaction2.empty());
using LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
// put_transaction<void> can be move assigned from any put_transaction<T>
static_assert(
std::is_assignable<
typename LfQueue::template put_transaction<void>,
typename LfQueue::template put_transaction<void> &&>::value,
"");
static_assert(
std::is_assignable<
typename LfQueue::template put_transaction<void>,
typename LfQueue::template put_transaction<int> &&>::value,
"");
// put_transaction<T> can be move assigned only from put_transaction<T>
static_assert(
!std::is_assignable<
typename LfQueue::template put_transaction<int>,
typename LfQueue::template put_transaction<void> &&>::value,
"");
static_assert(
!std::is_assignable<
typename LfQueue::template put_transaction<int>,
typename LfQueue::template put_transaction<float> &&>::value,
"");
static_assert(
std::is_assignable<
typename LfQueue::template put_transaction<int>,
typename LfQueue::template 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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue 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_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_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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue 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_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<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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue queue;
struct Msg
{
char * m_chars = nullptr;
};
auto post_message = [&queue](const std::string & i_string) {
auto transaction = queue.template start_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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue 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_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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue 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_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<put_transaction>().try_raw_allocate_copy( i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))
inlinenoexcept

Tries top 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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue queue;
struct Msg
{
char * m_chars = nullptr;
};
auto post_message = [&queue](const std::string & i_string) {
auto transaction = queue.template try_start_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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue queue;
// start and cancel a put
assert(queue.empty());
auto put = queue.start_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_push(42);
put.commit();
assert(queue.try_start_consume().template element<int>() == 42);
bool empty ( ) const
inlinenoexcept

Returns true whether this object is not currently bound to a transaction.

using LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue queue;
typename LfQueue::template put_transaction<> transaction;
assert(transaction.empty());
transaction = queue.start_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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue queue;
typename LfQueue::template put_transaction<> transaction;
assert(!transaction);
transaction = queue.start_push(1);
assert(transaction);
lf_heter_queue* queue ( ) const
inlinenoexcept

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

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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue queue;
int value = 42;
auto put = queue.start_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_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 the commit.
Note: An element is observable in the queue only after commit has been called on the 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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue 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 LfQueue = lf_heter_queue<
runtime_type<>,
PROD_CARDINALITY,
CONSUMER_CARDINALITY,
CONSISTENCY_MODEL>;
LfQueue queue;
int value = 42;
auto put = queue.start_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 ( put_transaction< ELEMENT_COMPLETE_TYPE > &  i_first,
put_transaction< ELEMENT_COMPLETE_TYPE > &  i_second 
)
friend

Swaps two instances of put_transaction.


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