ADTF  3.18.2
lockfreestack.h
Go to the documentation of this file.
1 
7 #ifndef _LOCK_FREE_STACK_CLASS_HEADER_
8 #define _LOCK_FREE_STACK_CLASS_HEADER_
9 
10 #include "tagged_ptr.h"
11 
12 #ifndef A_UTILS_TAGGED_POINTER_AVALIABLE
13  #include <stack>
14  using std::stack;
15 #endif
16 
17 
18 
19 namespace A_UTILS_NS
20 {
21 
22 #ifdef A_UTILS_TAGGED_POINTER_AVALIABLE
23 
39 template <class T>
40 class A_UTILS_CAS_ALIGNMENT lock_free_stack
41 {
42  protected:
43 
47  struct A_UTILS_CAS_ALIGNMENT cNode
48  {
49  tagged_ptr<cNode> m_pNext;
50  T m_oData;
51  };
52 
54  typedef tagged_ptr<cNode> tTaggedNodePtr;
55 
57  tTaggedNodePtr m_pLast;
58 
60  free_list<cNode, T> m_oFree;
61 
62  public:
63 
75  lock_free_stack(tUInt nReserve = 0, tBool bGrow = tTrue): m_pLast(nullptr), m_oFree(nReserve, bGrow)
76  {
77  }
78 
82  virtual ~lock_free_stack()
83  {
84  // clear stack
85  T oTmp;
86  while (static_cast<tErrorCode>(ERR_NOERROR) == Pop(&oTmp));
87  }
88 
95  tErrorCode Push(const T& oValue)
96  {
97  // get a node from the free list
98  cNode* pTmp = m_oFree.GetFreeNode();
99  if (!pTmp)
100  {
101  return static_cast<tErrorCode>(ERR_MEMORY);
102  }
103 
104  // store the value
105  pTmp->m_oData = oValue;
106  // and insert it into the list
107  tTaggedNodePtr pOld;
108  do
109  {
110  pOld.Set(m_pLast);
111  pTmp->m_pNext.Set(pOld.GetPtr());
112  }
113  while (!m_pLast.CompareAndSwap(pOld, pTmp)); // try insertion until we succeed
114 
115  return static_cast<tErrorCode>(ERR_NOERROR);
116  }
117 
125  tErrorCode Pop(T* pValue)
126  {
127  for (;;)
128  {
129  tTaggedNodePtr pOldTos;
130  pOldTos.Set(m_pLast);
131 
132  if (!pOldTos)
133  {
134  return static_cast<tErrorCode>(ERR_EMPTY);
135  }
136 
137  cNode* pNewTos = pOldTos->m_pNext.GetPtr();
138 
139  if (m_pLast.CompareAndSwap(pOldTos, pNewTos))
140  {
141  *pValue = pOldTos->m_oData;
142  m_oFree.AddFreeNode(pOldTos.GetPtr());
143  break;
144  }
145  }
146 
147  return static_cast<tErrorCode>(ERR_NOERROR);
148  }
149 
150  private:
151  lock_free_stack(const lock_free_stack& oOther);
152 };
153 
154 #else
155 
167 template <class T>
169 {
170  protected:
171  std::recursive_mutex m_oMutex;
172  std::stack<T> m_oStack;
173  public:
174 
185  lock_free_stack(tUInt nReserve = 0, tBool bGrow = tTrue)
186  {
187  }
188 
193  {
194  }
195 
201  tErrorCode Push(const T& oValue)
202  {
203  std::lock_guard<std::recursive_mutex> oLck(m_oMutex);
204  m_oStack.push(oValue);
205  return static_cast<tErrorCode>(ERR_NOERROR);
206  }
207 
214  tErrorCode Pop(T* pValue)
215  {
216  std::lock_guard<std::recursive_mutex> oLck(m_oMutex);
217  if (m_oStack.empty())
218  {
219  return static_cast<tErrorCode>(ERR_EMPTY);
220  }
221  *pValue = m_oStack.top();
222  m_oStack.pop();
223  return static_cast<tErrorCode>(ERR_NOERROR);
224  }
225 
226  private:
227  lock_free_stack(const lock_free_stack& oOther);
228 };
229 
230 #endif
231 
232 
233 }
234 
235 #endif
unsigned int tUInt
type definition for unsigned integer value (platform and compiler dependent type).
bool tBool
The tBool defines the type for the Values tTrue and tFalse (platform and compiler dependent).
Lock-free stack class that allows multiple writers and readers.
tErrorCode Pop(T *pValue)
Pops an element from the stack.
virtual ~lock_free_stack()
Destructor.
lock_free_stack(tUInt nReserve=0, tBool bGrow=tTrue)
Constructor.
tErrorCode Push(const T &oValue)
Pushes an element onto the stack.
#define tTrue
Value for tBool.
Definition: constants.h:62
ADTF A_UTIL Namespace - Within adtf this is used as adtf::util or adtf_util.
Definition: d_ptr.h:11
Copyright © Audi Electronics Venture GmbH.