Skip to content

Commit 68bfdcd

Browse files
committed
[include] Modify ConcurrentQueue to support emplace
(see cameron314/concurrentqueue#275)
1 parent 3002cf7 commit 68bfdcd

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

include/lockfree/concurrentqueue/concurrentqueue.h

+27-15
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,18 @@ class ConcurrentQueue
10081008
MOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;
10091009
else return inner_enqueue<CanAlloc>(std::move(item));
10101010
}
1011+
1012+
// Enqueues a single item (by constructing it in-place from arguments).
1013+
// Allocates memory if required. Only fails if memory allocation fails (or implicit
1014+
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,
1015+
// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
1016+
// Thread-safe.
1017+
template<typename... Args>
1018+
inline bool enqueue_emplace(Args&&... args)
1019+
{
1020+
MOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;
1021+
else return inner_enqueue<CanAlloc>(std::forward<Args>(args)...);
1022+
}
10111023

10121024
// Enqueues a single item (by copying it) using an explicit producer token.
10131025
// Allocates memory if required. Only fails if memory allocation fails (or
@@ -1369,11 +1381,11 @@ class ConcurrentQueue
13691381
return static_cast<ExplicitProducer*>(token.producer)->ConcurrentQueue::ExplicitProducer::template enqueue<canAlloc>(std::forward<U>(element));
13701382
}
13711383

1372-
template<AllocationMode canAlloc, typename U>
1373-
inline bool inner_enqueue(U&& element)
1384+
template<AllocationMode canAlloc, typename... Args>
1385+
inline bool inner_enqueue(Args&& ... args)
13741386
{
13751387
auto producer = get_or_add_implicit_producer();
1376-
return producer == nullptr ? false : producer->ConcurrentQueue::ImplicitProducer::template enqueue<canAlloc>(std::forward<U>(element));
1388+
return producer == nullptr ? false : producer->ConcurrentQueue::ImplicitProducer::template enqueue<canAlloc>(std::forward<Args>(args)...);
13771389
}
13781390

13791391
template<AllocationMode canAlloc, typename It>
@@ -1845,8 +1857,8 @@ class ConcurrentQueue
18451857
}
18461858
}
18471859

1848-
template<AllocationMode allocMode, typename U>
1849-
inline bool enqueue(U&& element)
1860+
template<AllocationMode allocMode, typename... Args>
1861+
inline bool enqueue(Args&&... args)
18501862
{
18511863
index_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed);
18521864
index_t newTailIndex = 1 + currentTailIndex;
@@ -1912,11 +1924,11 @@ class ConcurrentQueue
19121924
++pr_blockIndexSlotsUsed;
19131925
}
19141926

1915-
MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) {
1927+
MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<Args>(args)...))) {
19161928
// The constructor may throw. We want the element not to appear in the queue in
19171929
// that case (without corrupting the queue):
19181930
MOODYCAMEL_TRY {
1919-
new ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element));
1931+
new ((*this->tailBlock)[currentTailIndex]) T(std::forward<Args>(args)...);
19201932
}
19211933
MOODYCAMEL_CATCH (...) {
19221934
// Revert change to the current block, but leave the new block available
@@ -1938,14 +1950,14 @@ class ConcurrentQueue
19381950
blockIndex.load(std::memory_order_relaxed)->front.store(pr_blockIndexFront, std::memory_order_release);
19391951
pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);
19401952

1941-
MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) {
1953+
MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<Args>(args)...))) {
19421954
this->tailIndex.store(newTailIndex, std::memory_order_release);
19431955
return true;
19441956
}
19451957
}
19461958

19471959
// Enqueue
1948-
new ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element));
1960+
new ((*this->tailBlock)[currentTailIndex]) T(std::forward<Args>(args)...);
19491961

19501962
this->tailIndex.store(newTailIndex, std::memory_order_release);
19511963
return true;
@@ -2483,8 +2495,8 @@ class ConcurrentQueue
24832495
}
24842496
}
24852497

2486-
template<AllocationMode allocMode, typename U>
2487-
inline bool enqueue(U&& element)
2498+
template<AllocationMode allocMode, typename... Args>
2499+
inline bool enqueue(Args&&... args)
24882500
{
24892501
index_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed);
24902502
index_t newTailIndex = 1 + currentTailIndex;
@@ -2516,10 +2528,10 @@ class ConcurrentQueue
25162528
#endif
25172529
newBlock->ConcurrentQueue::Block::template reset_empty<implicit_context>();
25182530

2519-
MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) {
2531+
MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<Args>(args)...))) {
25202532
// May throw, try to insert now before we publish the fact that we have this new block
25212533
MOODYCAMEL_TRY {
2522-
new ((*newBlock)[currentTailIndex]) T(std::forward<U>(element));
2534+
new ((*newBlock)[currentTailIndex]) T(std::forward<Args>(args)...);
25232535
}
25242536
MOODYCAMEL_CATCH (...) {
25252537
rewind_block_index_tail();
@@ -2534,14 +2546,14 @@ class ConcurrentQueue
25342546

25352547
this->tailBlock = newBlock;
25362548

2537-
MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) {
2549+
MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<Args>(args)...))) {
25382550
this->tailIndex.store(newTailIndex, std::memory_order_release);
25392551
return true;
25402552
}
25412553
}
25422554

25432555
// Enqueue
2544-
new ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element));
2556+
new ((*this->tailBlock)[currentTailIndex]) T(std::forward<Args>(args)...);
25452557

25462558
this->tailIndex.store(newTailIndex, std::memory_order_release);
25472559
return true;

0 commit comments

Comments
 (0)