上源码
1 #ifndef __GLOBAL_LOCK_FREE_QUEUE_H__ 2 #define __GLOBAL_LOCK_FREE_QUEUE_H__ 3 4 #include <atomic> 5 #include <list> 6 7 #ifdef _WINDOWS 8 #include <windows.h> 9 //PVOID __cdecl InterlockedCompareExchangePointer( 10 // _Inout_ PVOID volatile *Destination, 11 // _In_ PVOID Exchange, 12 // _In_ PVOID Comparand 13 // ); 14 // 15 //Parameters 16 // Destination [in, out] 17 //A pointer to a pointer to the destination value. 18 // Exchange [in] 19 //The exchange value. 20 // Comparand [in] 21 //The value to compare to Destination. 22 // Return value 23 // The function returns the initial value of the Destination parameter. 24 // Remarks 25 // The function compares the Destination value with the Comparand value. If the Destination value is equal to the Comparand value, the Exchange value is stored in the address specified by Destination. Otherwise, no operation is performed. 26 // On a 64-bit system, the parameters are 64 bits and must be aligned on 64-bit boundaries; otherwise, the function will behave unpredictably. On a 32-bit system, the parameters are 32 bits and must be aligned on 32-bit boundaries. 27 // The interlocked functions provide a simple mechanism for synchronizing access to a variable that is shared by multiple threads. This function is atomic with respect to calls to other interlocked functions. 28 #define __sync_bool_compare_and_swap(a,b,c) (InterlockedCompareExchangePointer((void*volatile*)a,c,b), (*a)==(c)) 29 #endif 30 31 namespace DataCache 32 { 33 34 template <typename T> 35 class LinkList 36 { 37 public: 38 T data; 39 LinkList<T> *next; 40 };// class LinkeList<T> 41 42 template <typename T> 43 class LockFreeQueue 44 { 45 public: 46 LockFreeQueue(); 47 48 void push_back(T t); 49 50 T pop_front(void); 51 52 bool isEmpty(void); 53 54 int GetLength(); 55 56 private: 57 LinkList<T> *head_; 58 LinkList<T> *tail_; 59 std::_Atomic_integral_t elementNumbers_; 60 }; // class LockFreeQueue 61 62 template <typename T> 63 LockFreeQueue<T>::LockFreeQueue() 64 :head_(NULL), 65 tail_(new LinkList<T>), 66 elementNumbers_(0) 67 { 68 head_ = tail_; 69 tail_->next = NULL; 70 } 71 72 template <typename T> 73 void LockFreeQueue<T>::push_back(T t) 74 { 75 auto newVal = new LinkList<T>; 76 newVal->data = t; 77 newVal->next = NULL; 78 79 LinkList<T> *p; 80 do 81 { 82 p = tail_; 83 } while (!__sync_bool_compare_and_swap(&tail_->next, NULL, newVal)); 84 85 //move tail_ 86 __sync_bool_compare_and_swap(&tail_, tail_, newVal); 87 elementNumbers_++; 88 } 89 90 template <typename T> 91 T LockFreeQueue<T>::pop_front() 92 { 93 LinkList<T> *p; 94 95 do 96 { 97 //record the first node. 98 p = head_->next; 99 if (!p) 100 { 101 return 0; 102 } 103 } while (!__sync_bool_compare_and_swap(&head_->next, p, p->next)); 104 105 if (elementNumbers_ > 0) elementNumbers_--; 106 if (elementNumbers_ == 0) 107 { 108 // if the queue is empty then the tail to header. 109 do 110 { 111 112 } while (!__sync_bool_compare_and_swap(&tail_, p, head_)); 113 } 114 115 return p->data; 116 } 117 118 template <typename T> 119 bool LockFreeQueue<T>::isEmpty() 120 { 121 if (elementNumbers_ == 0) 122 { 123 return true; 124 } 125 else 126 { 127 return false; 128 } 129 } 130 131 template <typename T> 132 int LockFreeQueue<T>::GetLength() 133 { 134 return elementNumbers_; 135 } 136 137 }// namespace DataCache 138 139 #endif