From 082633f08aae8eea19bd7050cbe4a75e5ed1ac6f Mon Sep 17 00:00:00 2001
From: wangzhengquan <wangzhengquan85@126.com>
Date: 星期二, 07 七月 2020 12:07:29 +0800
Subject: [PATCH] update

---
 squeue/include/array_lock_free_queue.h |   91 ++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 81 insertions(+), 10 deletions(-)

diff --git a/squeue/include/lock_free_queue_impl_multiple_producer.h b/squeue/include/array_lock_free_queue.h
similarity index 71%
rename from squeue/include/lock_free_queue_impl_multiple_producer.h
rename to squeue/include/array_lock_free_queue.h
index 959cca8..8bcf579 100644
--- a/squeue/include/lock_free_queue_impl_multiple_producer.h
+++ b/squeue/include/array_lock_free_queue.h
@@ -4,11 +4,82 @@
 #include <assert.h> // assert()
 #include <sched.h>  // sched_yield()
 
+
+/// @brief implementation of an array based lock free queue with support for 
+///        multiple producers
+/// This class is prevented from being instantiated directly (all members and
+/// methods are private). To instantiate a multiple producers lock free queue 
+/// you must use the ArrayLockFreeQueue fachade:
+///   ArrayLockFreeQueue<int, 100, ArrayLockFreeQueue> q;
 template <typename ELEM_T>
-int ArrayLockFreeQueueMultipleProducers<ELEM_T>::m_reference = 0;
+class ArrayLockFreeQueue
+{
+    // ArrayLockFreeQueue will be using this' private members
+    template <
+        typename ELEM_T_, 
+        template <typename T> class Q_TYPE >
+    friend class LockFreeQueue;
+
+private:
+    /// @brief constructor of the class
+    ArrayLockFreeQueue(size_t qsize = LOCK_FREE_Q_DEFAULT_SIZE);
+    
+    virtual ~ArrayLockFreeQueue();
+    
+    inline uint32_t size();
+    
+    inline bool full();
+
+    inline bool empty();
+    
+    bool push(const ELEM_T &a_data);   
+    
+    bool pop(ELEM_T &a_data);
+    
+    /// @brief calculate the index in the circular array that corresponds
+    /// to a particular "count" value
+    inline uint32_t countToIndex(uint32_t a_count);
+    
+private:    
+    size_t Q_SIZE;
+    /// @brief array to keep the elements
+    ELEM_T *m_theQueue;
+
+    /// @brief where a new element will be inserted
+    std::atomic<uint32_t> m_writeIndex;
+
+    /// @brief where the next element where be extracted from
+    std::atomic<uint32_t> m_readIndex;
+    
+    /// @brief maximum read index for multiple producer queues
+    /// If it's not the same as m_writeIndex it means
+    /// there are writes pending to be "committed" to the queue, that means,
+    /// the place for the data was reserved (the index in the array) but  
+    /// data is still not in the queue, so the thread trying to read will have 
+    /// to wait for those other threads to save the data into the queue
+    ///
+    /// note this is only used for multiple producers
+    std::atomic<uint32_t> m_maximumReadIndex;
+
+#ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE
+    /// @brief number of elements in the queue
+    std::atomic<uint32_t> m_count;
+#endif
+    static int m_reference;
+
+private:
+    /// @brief disable copy constructor declaring it private
+    ArrayLockFreeQueue<ELEM_T>(const ArrayLockFreeQueue<ELEM_T> &a_src);
+
+
+};
+
 
 template <typename ELEM_T>
-ArrayLockFreeQueueMultipleProducers<ELEM_T>::ArrayLockFreeQueueMultipleProducers(size_t qsize):
+int ArrayLockFreeQueue<ELEM_T>::m_reference = 0;
+
+template <typename ELEM_T>
+ArrayLockFreeQueue<ELEM_T>::ArrayLockFreeQueue(size_t qsize):
     Q_SIZE(qsize),
     m_writeIndex(0),      // initialisation is not atomic
     m_readIndex(0),       //
@@ -23,9 +94,9 @@
 }
 
 template <typename ELEM_T>
-ArrayLockFreeQueueMultipleProducers<ELEM_T>::~ArrayLockFreeQueueMultipleProducers()
+ArrayLockFreeQueue<ELEM_T>::~ArrayLockFreeQueue()
 {
-    std::cout << "destroy ArrayLockFreeQueueMultipleProducers\n";
+    std::cout << "destroy ArrayLockFreeQueue\n";
     m_reference--;
     if(m_reference == 0) {
        mm_free(m_theQueue);
@@ -35,7 +106,7 @@
 
 template <typename ELEM_T>
 inline 
-uint32_t ArrayLockFreeQueueMultipleProducers<ELEM_T>::countToIndex(uint32_t a_count)
+uint32_t ArrayLockFreeQueue<ELEM_T>::countToIndex(uint32_t a_count)
 {
     // if Q_SIZE is a power of 2 this statement could be also written as 
     // return (a_count & (Q_SIZE - 1));
@@ -44,7 +115,7 @@
 
 template <typename ELEM_T>
 inline 
-uint32_t ArrayLockFreeQueueMultipleProducers<ELEM_T>::size()
+uint32_t ArrayLockFreeQueue<ELEM_T>::size()
 {
 #ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE
 
@@ -79,7 +150,7 @@
 
 template <typename ELEM_T>
 inline 
-bool ArrayLockFreeQueueMultipleProducers<ELEM_T>::full()
+bool ArrayLockFreeQueue<ELEM_T>::full()
 {
 #ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE
 
@@ -104,7 +175,7 @@
 
 template <typename ELEM_T>
 inline 
-bool ArrayLockFreeQueueMultipleProducers<ELEM_T>::empty()
+bool ArrayLockFreeQueue<ELEM_T>::empty()
 {
 #ifdef _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE
 
@@ -126,7 +197,7 @@
 
 
 template <typename ELEM_T>
-bool ArrayLockFreeQueueMultipleProducers<ELEM_T>::push(const ELEM_T &a_data)
+bool ArrayLockFreeQueue<ELEM_T>::push(const ELEM_T &a_data)
 {
     uint32_t currentWriteIndex;
     
@@ -187,7 +258,7 @@
 }
 
 template <typename ELEM_T>
-bool ArrayLockFreeQueueMultipleProducers<ELEM_T>::pop(ELEM_T &a_data)
+bool ArrayLockFreeQueue<ELEM_T>::pop(ELEM_T &a_data)
 {
     uint32_t currentReadIndex;
 

--
Gitblit v1.8.0