forked from treefrogframework/treefrog-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtatomicset.cpp
108 lines (86 loc) · 2.11 KB
/
tatomicset.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* Copyright (c) 2013, AOYAMA Kazuharu
* All rights reserved.
*
* This software may be used and distributed according to the terms of
* the New BSD License, which is incorporated herein by reference.
*/
#include <QAtomicPointer>
#include <QThread>
#include "tatomicset.h"
#include "tsystemglobal.h"
TAtomicSet::TAtomicSet()
: num(0), stack(0), itemCount(0)
{ }
TAtomicSet::TAtomicSet(int maxCount)
: num(maxCount), stack(new QAtomicPointer<void>[maxCount]), itemCount(0)
{ }
TAtomicSet::TAtomicSet(const QList<void*> items)
: num(items.count()), stack(new QAtomicPointer<void>[items.count()]), itemCount(0)
{
for (QListIterator<void*> it(items); it.hasNext(); ) {
push(it.next());
}
}
void TAtomicSet::setMaxCount(int count)
{
Q_ASSERT(!stack);
stack = new QAtomicPointer<void>[count];
num = count;
itemCount = 0;
}
TAtomicSet::~TAtomicSet()
{
if (stack)
delete[] stack;
}
void *TAtomicSet::pop()
{
void *ret = 0;
while (count() > 0) {
for (int i = 0; i < num; ++i) {
ret = stack[i].fetchAndStoreOrdered(0);
if (ret) {
itemCount.fetchAndAddOrdered(-1);
return ret;
}
}
QThread::yieldCurrentThread();
}
return ret;
}
bool TAtomicSet::push(void *item)
{
Q_CHECK_PTR(item);
bool ret = false;
while (count() < num) {
for (int i = 0; i < num; ++i) {
ret = stack[i].testAndSetOrdered(0, item);
if (ret) {
itemCount.fetchAndAddOrdered(1);
return ret;
}
}
QThread::yieldCurrentThread();
}
return ret;
}
// pop item without counter decrement
void *TAtomicSet::peekPop(int i)
{
return (stack) ? stack[i].fetchAndStoreOrdered(0) : 0;
}
// push item without counter increment
bool TAtomicSet::peekPush(void *item)
{
Q_CHECK_PTR(item);
bool ret = false;
if (!stack)
return ret;
for (int i = 0; i < num; ++i) {
ret = stack[i].testAndSetOrdered(0, item);
if (ret) {
return ret;
}
}
return ret;
}