Jamoma API  0.6.0.a19
TTQueue.cpp
1 /*
2  * TTBlue low-priority queue
3  * Copyright © 2008, Timothy Place
4  *
5  * License: This code is licensed under the terms of the "New BSD License"
6  * http://creativecommons.org/licenses/BSD/
7  */
8 
9 #include "TTQueue.h"
10 
11 
12 
13 #if OLD
14 
15 void* TTQueueMaster(void* anArgument)
16 {
17  TTQueue *queue = (TTQueue*)anArgument;
18 
19  return queue->run();
20 }
21 
22 
23 /****************************************************************************************************/
24 
25 TTQueue::TTQueue()
26  : queueThread(NULL)
27 {
28  queueThread = new TTThread(TTQueueMaster, this);
29  queueEventObjects = new TTList;
30  queueEventMethods = new TTList;
31  queueEventValues = new TTList;
32 }
33 
34 
35 TTQueue::~TTQueue()
36 {
37  if (queueThread)
38  delete queueThread;
39  delete queueEventObjects;
40  delete queueEventMethods;
41  delete queueEventValues;
42 }
43 
44 
45 // main loop for the queue
46 void* TTQueue::run()
47 {
48 /*
49  TTListItem* objectItem;
50  TTObject* object;
51  TTListItem* messageItem;
52  TTSymbol message;
53  TTListItem* valueItem;
54  TTValue value;
55  TTValue tempValue;
56 
57  while (1) {
58  objectItem = queueEventObjects->getHead(tempValue);
59  object = tempValue;
60  messageItem = queueEventObjects->getHead(tempValue);
61  message = tempValue;
62  valueItem = queueEventObjects->getHead(tempValue);
63  value = tempValue;
64 
65  object->sendMessage(message, value);
66 
67  TTThread::sleep(40); // 24 fps
68  // do we want to check every 40 ms? Or do we want to kill the thread and re-create it only when it is needed?
69  }
70  */
71  return NULL;
72 }
73 
74 
75 /** Add a call to the back of the queue. Will trigger the queue to be serviced if it isn't
76  already scheduled. */
77 void TTQueue::queueToBack(TTObject& anObject, TTSymbol aMessage, TTValue& aValue)
78 {
79  TTValue tempValue;
80 
81  tempValue = anObject;
82  queueEventObjects->append(tempValue);
83  tempValue = aMessage;
84  queueEventMethods->append(tempValue);
85  queueEventValues->append(aValue);
86 }
87 
88 #else
89 
90 TTQueue::TTQueue() :
91  mUpdateCounter(0),
92  mAcknowledgementCounter(0)
93 {
94  resize(32);
95 }
96 
97 
98 TTQueue::~TTQueue()
99 {
100  ;
101 }
102 
103 
105 {
106  TTUInt32 size = aNewSize;
107 
108  if (size != mBuffer.size() && TTIsPowerOfTwo(size)) {
109  mBuffer.resize(size);
110  mSize = size;
111  mTwiceSize = size * 2;
112  }
113  return kTTErrNone;
114 }
115 
116 
117 TTErr TTQueue::size(TTUInt32& returnedSize)
118 {
119  returnedSize = mSize;
120  return kTTErrNone;
121 }
122 
123 
124 // the counters are updated 2 times for successful inserts and reads
125 // when the update counter is odd, this indicates that we are in the middle of an insertion
126 
127 TTQueue::InsertStatus TTQueue::insert(const TTValue& anItem)
128 {
129  TTUInt32 lastUpdateCounter = mUpdateCounter;
130  TTUInt32 lastAcknowledgementCounter = mAcknowledgementCounter; // this read should be atomic
131  TTUInt32 counterDifference = lastUpdateCounter - lastAcknowledgementCounter;
132  TTUInt32 index;
133 
134  if (counterDifference == mTwiceSize)
135  return kBufferFull;
136  if (counterDifference == mTwiceSize-1)
137  return kBufferFullButCurrentlyReading;
138 
139  TTAtomicIncrement(mUpdateCounter); // now odd, indicating that we are in the middle of an insertion
140 
141  index = (lastUpdateCounter/2) & (mSize-1); // fast modulo for power of 2
142  mBuffer[index] = anItem; // copy
143 
144  TTAtomicIncrement(mUpdateCounter); // now even, indicating that the insertion has completed
145  return kBufferInsertSuccessful;
146 }
147 
148 
149 TTQueue::ReadStatus TTQueue::read(TTValue& returnedItem)
150 {
151  TTUInt32 lastUpdateCounter = mUpdateCounter; // this read should be atomic
152  TTUInt32 lastAcknowledgementCounter = mAcknowledgementCounter;
153  TTUInt32 index;
154 
155  if (lastUpdateCounter == lastAcknowledgementCounter)
156  return kBufferEmpty;
157  if (lastUpdateCounter - lastAcknowledgementCounter == 1)
158  return kBufferEmptyButCurrentlyWriting;
159 
160  TTAtomicIncrement(mAcknowledgementCounter); // now odd, indicating that we are in the middle of an insertion
161 
162  index = (lastAcknowledgementCounter/2) & (mSize-1); // fast modulo for power of 2
163  returnedItem = mBuffer[index]; // copy
164 
165  TTAtomicIncrement(mAcknowledgementCounter); // now even, indicating that the read has completed
166 
167  return kBufferReadSuccessful;
168 }
169 
170 
171 #endif
172 
TTErr resize(TTUInt32 aNewSize)
attribute accessor
Definition: TTQueue.cpp:104
ReadStatus read(TTValue &returnedItem)
get the next event and pop it from the queue.
Definition: TTQueue.cpp:149
Create and use Jamoma object instances.
Definition: TTObject.h:29
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
InsertStatus insert(const TTValue &anItem)
add an item to the queue.
Definition: TTQueue.cpp:127
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
No Error.
Definition: TTBase.h:343
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
The TTQueue class implements a non-blocking circular queue for passing events across threads...
Definition: TTQueue.h:135