Krita Source Code Documentation
Loading...
Searching...
No Matches
KisLocklessStack< T > Class Template Reference

#include <kis_lockless_stack.h>

Classes

struct  Node
 

Public Member Functions

void clear ()
 
bool isEmpty () const
 
 KisLocklessStack ()
 
void mergeFrom (KisLocklessStack< T > &other)
 
bool pop (T &value)
 
void push (T data)
 
qint32 size () const
 
 ~KisLocklessStack ()
 

Private Member Functions

void cleanUpNodes ()
 
void freeList (Node *first)
 
void releaseNode (Node *node)
 

Private Attributes

QAtomicInt m_deleteBlockers
 
QAtomicPointer< Nodem_freeNodes
 
QAtomicInt m_numNodes
 
QAtomicPointer< Nodem_top
 

Detailed Description

template<class T>
class KisLocklessStack< T >

Definition at line 23 of file kis_lockless_stack.h.

Constructor & Destructor Documentation

◆ KisLocklessStack()

template<class T >
KisLocklessStack< T >::KisLocklessStack ( )
inline

Definition at line 32 of file kis_lockless_stack.h.

32{ }

◆ ~KisLocklessStack()

template<class T >
KisLocklessStack< T >::~KisLocklessStack ( )
inline

Definition at line 33 of file kis_lockless_stack.h.

33 {
34
35 freeList(m_top.fetchAndStoreOrdered(0));
36 freeList(m_freeNodes.fetchAndStoreOrdered(0));
37 }
QAtomicPointer< Node > m_freeNodes
QAtomicPointer< Node > m_top
void freeList(Node *first)

References KisLocklessStack< T >::freeList(), KisLocklessStack< T >::m_freeNodes, and KisLocklessStack< T >::m_top.

Member Function Documentation

◆ cleanUpNodes()

template<class T >
void KisLocklessStack< T >::cleanUpNodes ( )
inlineprivate

If we are the only users of the objects is cleanChain, then just free it. Otherwise, push them back into the recycling list and keep them there till another chance comes.

Definition at line 177 of file kis_lockless_stack.h.

177 {
178 Node *cleanChain = m_freeNodes.fetchAndStoreOrdered(0);
179 if (!cleanChain) return;
180
187 if (m_deleteBlockers == 1) {
188 freeList(cleanChain);
189 } else {
190 Node *last = cleanChain;
191 while (last->next) last = last->next;
192
193 Node *freeTop;
194
195 do {
196 freeTop = m_freeNodes;
197 last->next = freeTop;
198 } while (!m_freeNodes.testAndSetOrdered(freeTop, cleanChain));
199 }
200 }
Definition Node.h:24

References KisLocklessStack< T >::freeList(), KisLocklessStack< T >::m_deleteBlockers, KisLocklessStack< T >::m_freeNodes, and KisLocklessStack< T >::Node::next.

◆ clear()

template<class T >
void KisLocklessStack< T >::clear ( )
inline

We are the only owner of top contents. So we can delete it freely.

Definition at line 94 of file kis_lockless_stack.h.

94 {
95 // a fast-path without write ops
96 if(!m_top) return;
97
98 m_deleteBlockers.ref();
99
100 Node *top = m_top.fetchAndStoreOrdered(0);
101
102 int removedChunkSize = 0;
103 Node *tmp = top;
104 while(tmp) {
105 removedChunkSize++;
106 tmp = tmp->next;
107 }
108 m_numNodes.fetchAndAddOrdered(-removedChunkSize);
109
110 while(top) {
111 Node *next = top->next;
112
113 if (m_deleteBlockers == 1) {
118 cleanUpNodes();
119 freeList(top);
120 next = 0;
121 }
122 else {
123 releaseNode(top);
124 }
125
126 top = next;
127 }
128
129 m_deleteBlockers.deref();
130 }
void releaseNode(Node *node)
QAction * next(const QObject *recvr, const char *slot, QObject *parent)

References KisLocklessStack< T >::cleanUpNodes(), KisLocklessStack< T >::freeList(), KisLocklessStack< T >::m_deleteBlockers, KisLocklessStack< T >::m_numNodes, KisLocklessStack< T >::m_top, KisLocklessStack< T >::Node::next, and KisLocklessStack< T >::releaseNode().

◆ freeList()

template<class T >
void KisLocklessStack< T >::freeList ( Node * first)
inlineprivate

Definition at line 202 of file kis_lockless_stack.h.

202 {
203 Node *next;
204 while (first) {
205 next = first->next;
206 delete first;
207 first = next;
208 }
209 }

References KisLocklessStack< T >::Node::next.

◆ isEmpty()

template<class T >
bool KisLocklessStack< T >::isEmpty ( ) const
inline

Definition at line 163 of file kis_lockless_stack.h.

163 {
164 return !m_numNodes;
165 }

References KisLocklessStack< T >::m_numNodes.

◆ mergeFrom()

template<class T >
void KisLocklessStack< T >::mergeFrom ( KisLocklessStack< T > & other)
inline

Definition at line 132 of file kis_lockless_stack.h.

132 {
133 Node *otherTop = other.m_top.fetchAndStoreOrdered(0);
134 if (!otherTop) return;
135
136 int removedChunkSize = 1;
137 Node *last = otherTop;
138 while(last->next) {
139 removedChunkSize++;
140 last = last->next;
141 }
142 other.m_numNodes.fetchAndAddOrdered(-removedChunkSize);
143
144 Node *top;
145
146 do {
147 top = m_top;
148 last->next = top;
149 } while (!m_top.testAndSetOrdered(top, otherTop));
150
151 m_numNodes.fetchAndAddOrdered(removedChunkSize);
152 }

References KisLocklessStack< T >::m_numNodes, KisLocklessStack< T >::m_top, and KisLocklessStack< T >::Node::next.

◆ pop()

template<class T >
bool KisLocklessStack< T >::pop ( T & value)
inline

Test if we are the only delete blocker left (it means that we are the only owner of 'top') If there is someone else in "delete-blocked section", then just add the struct to the list of free nodes.

Definition at line 53 of file kis_lockless_stack.h.

53 {
54 bool result = false;
55
56 m_deleteBlockers.ref();
57
58 while(1) {
59 Node *top = (Node*) m_top;
60 if(!top) break;
61
62 // This is safe as we ref'ed m_deleteBlockers
63 Node *next = top->next;
64
65 if(m_top.testAndSetOrdered(top, next)) {
66 m_numNodes.deref();
67 result = true;
68
69 value = top->data;
70
77 if (m_deleteBlockers == 1) {
79 delete top;
80 }
81 else {
82 releaseNode(top);
83 }
84
85 break;
86 }
87 }
88
89 m_deleteBlockers.deref();
90
91 return result;
92 }
float value(const T *src, size_t ch)

References KisLocklessStack< T >::cleanUpNodes(), KisLocklessStack< T >::Node::data, KisLocklessStack< T >::m_deleteBlockers, KisLocklessStack< T >::m_numNodes, KisLocklessStack< T >::m_top, KisLocklessStack< T >::Node::next, KisLocklessStack< T >::releaseNode(), and value().

◆ push()

template<class T >
void KisLocklessStack< T >::push ( T data)
inline

Definition at line 39 of file kis_lockless_stack.h.

39 {
40 Node *newNode = new Node();
41 newNode->data = data;
42
43 Node *top;
44
45 do {
46 top = m_top;
47 newNode->next = top;
48 } while (!m_top.testAndSetOrdered(top, newNode));
49
50 m_numNodes.ref();
51 }

References KisLocklessStack< T >::Node::data, KisLocklessStack< T >::m_numNodes, KisLocklessStack< T >::m_top, and KisLocklessStack< T >::Node::next.

◆ releaseNode()

template<class T >
void KisLocklessStack< T >::releaseNode ( Node * node)
inlineprivate

Definition at line 169 of file kis_lockless_stack.h.

169 {
170 Node *top;
171 do {
172 top = m_freeNodes;
173 node->next = top;
174 } while (!m_freeNodes.testAndSetOrdered(top, node));
175 }

References KisLocklessStack< T >::m_freeNodes, and KisLocklessStack< T >::Node::next.

◆ size()

template<class T >
qint32 KisLocklessStack< T >::size ( ) const
inline

This is impossible to measure the size of the stack in highly concurrent environment. So we return approximate value! Do not rely on this value much!

Definition at line 159 of file kis_lockless_stack.h.

159 {
160 return m_numNodes;
161 }

References KisLocklessStack< T >::m_numNodes.

Member Data Documentation

◆ m_deleteBlockers

template<class T >
QAtomicInt KisLocklessStack< T >::m_deleteBlockers
private

Definition at line 218 of file kis_lockless_stack.h.

◆ m_freeNodes

template<class T >
QAtomicPointer<Node> KisLocklessStack< T >::m_freeNodes
private

Definition at line 216 of file kis_lockless_stack.h.

◆ m_numNodes

template<class T >
QAtomicInt KisLocklessStack< T >::m_numNodes
private

Definition at line 219 of file kis_lockless_stack.h.

◆ m_top

template<class T >
QAtomicPointer<Node> KisLocklessStack< T >::m_top
private

Definition at line 215 of file kis_lockless_stack.h.


The documentation for this class was generated from the following file: