23#include "lockfreequeue_p.h"
25#include <QWriteLocker>
26#include <QReadWriteLock>
28#include "globalstatic_p.h"
41void MemoryPool::clear()
43 LockFreeQueueBase::NodeBase *node = stack;
45 if (stack.
testAndSetAcquire(node,
const_cast<LockFreeQueueBase::NodeBase *
>(node->next))) {
53MemoryPool::~MemoryPool()
55 LockFreeQueueBase::NodeBase *node = stack;
57 void *toDelete = node;
58 node =
const_cast<LockFreeQueueBase::NodeBase *
>(node->next);
63struct MemoryPoolVector
65 static const int POOL_COUNT = 16;
66 ~MemoryPoolVector() {
delete next; }
67 inline MemoryPool &operator[](
size_t s)
69 for (
int i = 0; i < POOL_COUNT; ++i) {
70 if (m_pools[i].size ==
static_cast<int>(s)) {
72 }
else if (m_pools[i].size == 0) {
73 if (m_pools[i].size.testAndSetRelaxed(0,
static_cast<int>(s))) {
76 if (m_pools[i].size ==
static_cast<int>(s)) {
82 MemoryPoolVector *newPoolVector =
new MemoryPoolVector;
92 for (
int i = 0; i < POOL_COUNT; ++i) {
93 if (0 == m_pools[i].size) {
99 next->clearAllPools();
103 MemoryPool m_pools[POOL_COUNT];
107static int s_poolSize = 128;
108PHONON_GLOBAL_STATIC(MemoryPoolVector, s_memoryPool)
110void *LockFreeQueueBase::NodeBaseKeepNodePool::operator
new(
size_t s)
112 MemoryPool &p = (*s_memoryPool)[s];
113 NodeBase *node = p.stack;
124void LockFreeQueueBase::NodeBaseKeepNodePool::operator
delete(
void *ptr,
size_t s)
126 MemoryPool &p = (*s_memoryPool)[s];
127 if (p.count > s_poolSize) {
131 NodeBase *node =
static_cast<NodeBase *
>(ptr);
132 NodeBase *
next = p.stack;
141void LockFreeQueueBase::NodeBaseKeepNodePool::clear()
143 s_memoryPool->clearAllPools();
146void LockFreeQueueBase::NodeBaseKeepNodePool::setPoolSize(
int s)
151int LockFreeQueueBase::NodeBaseKeepNodePool::poolSize()
156class LockFreeQueueBasePrivate
159 LockFreeQueueBasePrivate();
160 ~LockFreeQueueBasePrivate();
162 LockFreeQueueBase::NodeBase *sentinel;
163 LockFreeQueueBase::NodeBase *lastHeadNode;
167 LockFreeQueueBase::DataReadyHandler *dataReadyHandler;
170LockFreeQueueBasePrivate::LockFreeQueueBasePrivate()
171 : sentinel(new LockFreeQueueBase::NodeBase(0)),
172 lastHeadNode(new LockFreeQueueBase::NodeBase(sentinel)),
173 queueHead(&lastHeadNode->
next),
174 queueTail(&lastHeadNode->
next),
180 sentinel->next = sentinel;
183LockFreeQueueBasePrivate::~LockFreeQueueBasePrivate()
186 LockFreeQueueBase::NodeBase *node = lastHeadNode;
187 while (node != sentinel) {
188 LockFreeQueueBase::NodeBase *toDelete = node;
189 node =
const_cast<LockFreeQueueBase::NodeBase *
>(node->next);
194LockFreeQueueBase::LockFreeQueueBase()
195 : d(new LockFreeQueueBasePrivate)
199LockFreeQueueBase::~LockFreeQueueBase()
204void LockFreeQueueBase::setDataReadyHandler(DataReadyHandler *h)
207 d->dataReadyHandler = h;
210void LockFreeQueueBase::_enqueue(NodeBase *newNode)
213 newNode->next = d->sentinel;
228 NodeBasePointer &lastNextPointer = *d->queueTail.fetchAndStoreAcquire(&newNode->next);
229 lastNextPointer = newNode;
232 if (d->dataReadyHandler) {
234 if (d->dataReadyHandler) {
235 d->dataReadyHandler->dataReady();
241LockFreeQueueBase::NodeBase *LockFreeQueueBase::_acquireHeadNodeBlocking()
243 NodeBasePointer *node = 0;
244 while (d->size > 0) {
245 if ((node = d->queueHead.fetchAndStoreRelaxed(&d->sentinel->next)) != &d->sentinel->next) {
247 if (*node != d->sentinel) {
249 NodeBase *_node =
const_cast<NodeBase *
>(*node);
252 NodeBase *toDeref = d->lastHeadNode;
253 d->lastHeadNode = _node;
254 const bool check = d->queueHead.testAndSetRelease(&d->sentinel->next, &_node->next);
255 Q_ASSERT(check); Q_UNUSED(check);
261 const bool check = d->queueHead.testAndSetRelaxed(&d->sentinel->next, node);
262 Q_ASSERT(check); Q_UNUSED(check);
269LockFreeQueueBase::NodeBase *LockFreeQueueBase::_acquireHeadNode()
271 if (*d->queueHead == d->sentinel || d->queueHead == &d->sentinel->next) {
277 NodeBasePointer *node = d->queueHead.fetchAndStoreRelaxed(&d->sentinel->next);
278 if (node == &d->sentinel->next) {
286 if (*node == d->sentinel) {
288 const bool check = d->queueHead.testAndSetRelaxed(&d->sentinel->next, node);
289 Q_ASSERT(check); Q_UNUSED(check);
294 NodeBase *_node =
const_cast<NodeBase *
>(*node);
297 NodeBase *toDeref = d->lastHeadNode;
298 d->lastHeadNode = _node;
299 const bool check = d->queueHead.testAndSetRelease(&d->sentinel->next, &_node->next);
300 Q_ASSERT(check); Q_UNUSED(check);
306int LockFreeQueueBase::size()
const
QAction * next(const QObject *recvr, const char *slot, QObject *parent)
bool testAndSetAcquire(T *expectedValue, T *newValue)
bool testAndSetOrdered(T *expectedValue, T *newValue)
bool testAndSetRelaxed(T *expectedValue, T *newValue)