[med-svn] [Git][med-team/readerwriterqueue][upstream] New upstream version 1.0.6
Lance Lin (@linqigang)
gitlab at salsa.debian.org
Mon Aug 15 14:58:03 BST 2022
Lance Lin pushed to branch upstream at Debian Med / readerwriterqueue
Commits:
0ef22dda by Lance Lin at 2022-08-15T20:50:43+07:00
New upstream version 1.0.6
- - - - -
3 changed files:
- README.md
- atomicops.h
- readerwritercircularbuffer.h
Changes:
=====================================
README.md
=====================================
@@ -1,3 +1,4 @@
+
# A single-producer, single-consumer lock-free queue for C++
This mini-repository has my very own implementation of a lock-free queue (that I designed from scratch) for C++.
@@ -115,7 +116,37 @@ q.wait_dequeue_timed(number, std::chrono::milliseconds(10));
```
-## CMake installation
+## CMake
+### Using targets in your project
+Using this project as a part of an existing CMake project is easy.
+
+In your CMakeLists.txt:
+```
+include(FetchContent)
+
+FetchContent_Declare(
+ readerwriterqueue
+ GIT_REPOSITORY https://github.com/cameron314/readerwriterqueue
+ GIT_TAG master
+)
+
+FetchContent_MakeAvailable(readerwriterqueue)
+
+add_library(my_target main.cpp)
+target_link_libraries(my_target PUBLIC readerwriterqueue)
+```
+
+In main.cpp:
+```cpp
+#include <readerwriterqueue.h>
+
+int main()
+{
+ moodycamel::ReaderWriterQueue<int> q(100);
+}
+```
+
+### Installing into system directories
As an alternative to including the source files in your project directly,
you can use CMake to install the library in your system's include directory:
=====================================
atomicops.h
=====================================
@@ -43,16 +43,27 @@
// AE_UNUSED
#define AE_UNUSED(x) ((void)x)
-// AE_NO_TSAN
+// AE_NO_TSAN/AE_TSAN_ANNOTATE_*
#if defined(__has_feature)
#if __has_feature(thread_sanitizer)
+#if __cplusplus >= 201703L // inline variables require C++17
+namespace moodycamel { inline int ae_tsan_global; }
+#define AE_TSAN_ANNOTATE_RELEASE() AnnotateHappensBefore(__FILE__, __LINE__, (void *)(&::moodycamel::ae_tsan_global))
+#define AE_TSAN_ANNOTATE_ACQUIRE() AnnotateHappensAfter(__FILE__, __LINE__, (void *)(&::moodycamel::ae_tsan_global))
+extern "C" void AnnotateHappensBefore(const char*, int, void*);
+extern "C" void AnnotateHappensAfter(const char*, int, void*);
+#else // when we can't work with tsan, attempt to disable its warnings
#define AE_NO_TSAN __attribute__((no_sanitize("thread")))
-#else
-#define AE_NO_TSAN
#endif
-#else
+#endif
+#endif
+#ifndef AE_NO_TSAN
#define AE_NO_TSAN
#endif
+#ifndef AE_TSAN_ANNOTATE_RELEASE
+#define AE_TSAN_ANNOTATE_RELEASE()
+#define AE_TSAN_ANNOTATE_ACQUIRE()
+#endif
// AE_FORCEINLINE
@@ -208,10 +219,10 @@ AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN
{
switch (order) {
case memory_order_relaxed: break;
- case memory_order_acquire: std::atomic_thread_fence(std::memory_order_acquire); break;
- case memory_order_release: std::atomic_thread_fence(std::memory_order_release); break;
- case memory_order_acq_rel: std::atomic_thread_fence(std::memory_order_acq_rel); break;
- case memory_order_seq_cst: std::atomic_thread_fence(std::memory_order_seq_cst); break;
+ case memory_order_acquire: AE_TSAN_ANNOTATE_ACQUIRE(); std::atomic_thread_fence(std::memory_order_acquire); break;
+ case memory_order_release: AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_release); break;
+ case memory_order_acq_rel: AE_TSAN_ANNOTATE_ACQUIRE(); AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_acq_rel); break;
+ case memory_order_seq_cst: AE_TSAN_ANNOTATE_ACQUIRE(); AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_seq_cst); break;
default: assert(false);
}
}
@@ -352,6 +363,10 @@ extern "C" {
#include <mach/mach.h>
#elif defined(__unix__)
#include <semaphore.h>
+#elif defined(FREERTOS)
+#include <FreeRTOS.h>
+#include <semphr.h>
+#include <task.h>
#endif
namespace moodycamel
@@ -566,6 +581,73 @@ namespace moodycamel
}
}
};
+#elif defined(FREERTOS)
+ //---------------------------------------------------------
+ // Semaphore (FreeRTOS)
+ //---------------------------------------------------------
+ class Semaphore
+ {
+ private:
+ SemaphoreHandle_t m_sema;
+
+ Semaphore(const Semaphore& other);
+ Semaphore& operator=(const Semaphore& other);
+
+ public:
+ AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema()
+ {
+ assert(initialCount >= 0);
+ m_sema = xSemaphoreCreateCounting(static_cast<UBaseType_t>(~0ull), static_cast<UBaseType_t>(initialCount));
+ assert(m_sema);
+ }
+
+ AE_NO_TSAN ~Semaphore()
+ {
+ vSemaphoreDelete(m_sema);
+ }
+
+ bool wait() AE_NO_TSAN
+ {
+ return xSemaphoreTake(m_sema, portMAX_DELAY) == pdTRUE;
+ }
+
+ bool try_wait() AE_NO_TSAN
+ {
+ // Note: In an ISR context, if this causes a task to unblock,
+ // the caller won't know about it
+ if (xPortIsInsideInterrupt())
+ return xSemaphoreTakeFromISR(m_sema, NULL) == pdTRUE;
+ return xSemaphoreTake(m_sema, 0) == pdTRUE;
+ }
+
+ bool timed_wait(std::uint64_t usecs) AE_NO_TSAN
+ {
+ std::uint64_t msecs = usecs / 1000;
+ TickType_t ticks = static_cast<TickType_t>(msecs / portTICK_PERIOD_MS);
+ if (ticks == 0)
+ return try_wait();
+ return xSemaphoreTake(m_sema, ticks) == pdTRUE;
+ }
+
+ void signal() AE_NO_TSAN
+ {
+ // Note: In an ISR context, if this causes a task to unblock,
+ // the caller won't know about it
+ BaseType_t rc;
+ if (xPortIsInsideInterrupt())
+ rc = xSemaphoreGiveFromISR(m_sema, NULL);
+ else
+ rc = xSemaphoreGive(m_sema);
+ assert(rc == pdTRUE);
+ AE_UNUSED(rc);
+ }
+
+ void signal(int count) AE_NO_TSAN
+ {
+ while (count-- > 0)
+ signal();
+ }
+ };
#else
#error Unsupported platform! (No semaphore wrapper available)
#endif
=====================================
readerwritercircularbuffer.h
=====================================
@@ -33,7 +33,7 @@ public:
public:
explicit BlockingReaderWriterCircularBuffer(std::size_t capacity)
: maxcap(capacity), mask(), rawData(), data(),
- slots(new spsc_sema::LightweightSemaphore(static_cast<spsc_sema::LightweightSemaphore::ssize_t>(capacity))),
+ slots_(new spsc_sema::LightweightSemaphore(static_cast<spsc_sema::LightweightSemaphore::ssize_t>(capacity))),
items(new spsc_sema::LightweightSemaphore(0)),
nextSlot(0), nextItem(0)
{
@@ -52,7 +52,7 @@ public:
BlockingReaderWriterCircularBuffer(BlockingReaderWriterCircularBuffer&& other)
: maxcap(0), mask(0), rawData(nullptr), data(nullptr),
- slots(new spsc_sema::LightweightSemaphore(0)),
+ slots_(new spsc_sema::LightweightSemaphore(0)),
items(new spsc_sema::LightweightSemaphore(0)),
nextSlot(), nextItem()
{
@@ -86,7 +86,7 @@ public:
std::swap(mask, other.mask);
std::swap(rawData, other.rawData);
std::swap(data, other.data);
- std::swap(slots, other.slots);
+ std::swap(slots_, other.slots_);
std::swap(items, other.items);
std::swap(nextSlot, other.nextSlot);
std::swap(nextItem, other.nextItem);
@@ -98,7 +98,7 @@ public:
// No exception guarantee (state will be corrupted) if constructor of T throws.
bool try_enqueue(T const& item)
{
- if (!slots->tryWait())
+ if (!slots_->tryWait())
return false;
inner_enqueue(item);
return true;
@@ -110,7 +110,7 @@ public:
// No exception guarantee (state will be corrupted) if constructor of T throws.
bool try_enqueue(T&& item)
{
- if (!slots->tryWait())
+ if (!slots_->tryWait())
return false;
inner_enqueue(std::move(item));
return true;
@@ -122,7 +122,7 @@ public:
// No exception guarantee (state will be corrupted) if constructor of T throws.
void wait_enqueue(T const& item)
{
- while (!slots->wait());
+ while (!slots_->wait());
inner_enqueue(item);
}
@@ -132,7 +132,7 @@ public:
// No exception guarantee (state will be corrupted) if constructor of T throws.
void wait_enqueue(T&& item)
{
- while (!slots->wait());
+ while (!slots_->wait());
inner_enqueue(std::move(item));
}
@@ -143,7 +143,7 @@ public:
// No exception guarantee (state will be corrupted) if constructor of T throws.
bool wait_enqueue_timed(T const& item, std::int64_t timeout_usecs)
{
- if (!slots->wait(timeout_usecs))
+ if (!slots_->wait(timeout_usecs))
return false;
inner_enqueue(item);
return true;
@@ -156,7 +156,7 @@ public:
// No exception guarantee (state will be corrupted) if constructor of T throws.
bool wait_enqueue_timed(T&& item, std::int64_t timeout_usecs)
{
- if (!slots->wait(timeout_usecs))
+ if (!slots_->wait(timeout_usecs))
return false;
inner_enqueue(std::move(item));
return true;
@@ -262,7 +262,7 @@ private:
T& element = reinterpret_cast<T*>(data)[i & mask];
item = std::move(element);
element.~T();
- slots->signal();
+ slots_->signal();
}
template<typename U>
@@ -277,8 +277,8 @@ private:
std::size_t mask; // circular buffer capacity mask (for cheap modulo)
char* rawData; // raw circular buffer memory
char* data; // circular buffer memory aligned to element alignment
- std::unique_ptr<spsc_sema::LightweightSemaphore> slots; // number of slots currently free
- std::unique_ptr<spsc_sema::LightweightSemaphore> items; // number of elements currently enqueued
+ std::unique_ptr<spsc_sema::LightweightSemaphore> slots_; // number of slots currently free (named with underscore to accommodate Qt's 'slots' macro)
+ std::unique_ptr<spsc_sema::LightweightSemaphore> items; // number of elements currently enqueued
char cachelineFiller0[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(char*) * 2 - sizeof(std::size_t) * 2 - sizeof(std::unique_ptr<spsc_sema::LightweightSemaphore>) * 2];
std::size_t nextSlot; // index of next free slot to enqueue into
char cachelineFiller1[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(std::size_t)];
View it on GitLab: https://salsa.debian.org/med-team/readerwriterqueue/-/commit/0ef22ddac943a5a033c759b682e0c7d27899ed0f
--
View it on GitLab: https://salsa.debian.org/med-team/readerwriterqueue/-/commit/0ef22ddac943a5a033c759b682e0c7d27899ed0f
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20220815/b49e2f59/attachment-0001.htm>
More information about the debian-med-commit
mailing list