![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
A single producer consumer implementation without critical sections.
#include <SingleProducerConsumer.h>
Inheritance diagram for DataStructures::SingleProducerConsumer< SingleProducerConsumerType >:Classes | |
| struct | DataPlusPtr |
Public Member Functions | |
| void | CancelReadLock (SingleProducerConsumerType *cancelToLocation) |
| param[in] Which ReadLock() to cancel. | |
| void | CancelWriteLock (SingleProducerConsumerType *cancelToLocation) |
| bool | CheckReadUnlockOrder (const SingleProducerConsumerType *data) const |
| void | Clear (void) |
| Clear is not thread-safe and none of the lock or unlock functions should be called while it is running. | |
| bool | ReadIsLocked (void) const |
| SingleProducerConsumerType * | ReadLock (void) |
| void | ReadUnlock (void) |
| SingleProducerConsumer () | |
| int | Size (void) const |
| SingleProducerConsumerType * | WriteLock (void) |
| void | WriteUnlock (void) |
| Call when you are done writing to a block of memory returned by WriteLock() | |
| ~SingleProducerConsumer () | |
Private Attributes | |
| volatile DataPlusPtr * | readAheadPointer |
| unsigned | readCount |
| volatile DataPlusPtr * | readPointer |
| volatile DataPlusPtr * | writeAheadPointer |
| unsigned | writeCount |
| volatile DataPlusPtr * | writePointer |
Definition at line 25 of file SingleProducerConsumer.h.
| DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::SingleProducerConsumer | ( | ) |
Definition at line 92 of file SingleProducerConsumer.h.
References _FILE_AND_LINE_, MINIMUM_LIST_SIZE, and RakAssert.
{
// Preallocate
readPointer = RakNet::OP_NEW<DataPlusPtr>( _FILE_AND_LINE_ );
writePointer=readPointer;
readPointer->next = RakNet::OP_NEW<DataPlusPtr>( _FILE_AND_LINE_ );
int listSize;
#ifdef _DEBUG
RakAssert(MINIMUM_LIST_SIZE>=3);
#endif
for (listSize=2; listSize < MINIMUM_LIST_SIZE; listSize++)
{
readPointer=readPointer->next;
readPointer->next = RakNet::OP_NEW<DataPlusPtr>( _FILE_AND_LINE_ );
}
readPointer->next->next=writePointer; // last to next = start
readPointer=writePointer;
readAheadPointer=readPointer;
writeAheadPointer=writePointer;
readCount=writeCount=0;
}
| DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::~SingleProducerConsumer | ( | ) |
Definition at line 115 of file SingleProducerConsumer.h.
References _FILE_AND_LINE_, DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::DataPlusPtr::next, and RakNet::OP_DELETE().
{
volatile DataPlusPtr *next;
readPointer=writeAheadPointer->next;
while (readPointer!=writeAheadPointer)
{
next=readPointer->next;
RakNet::OP_DELETE((char*) readPointer, _FILE_AND_LINE_);
readPointer=next;
}
RakNet::OP_DELETE((char*) readPointer, _FILE_AND_LINE_);
}
| void DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::CancelReadLock | ( | SingleProducerConsumerType * | cancelToLocation | ) |
Definition at line 185 of file SingleProducerConsumer.h.
References RakAssert.
{
#ifdef _DEBUG
RakAssert(readPointer!=writePointer);
#endif
readAheadPointer=(DataPlusPtr *)cancelToLocation;
}
| void DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::CancelWriteLock | ( | SingleProducerConsumerType * | cancelToLocation | ) |
Call if you don't want to write to a block of data from WriteLock() after all. Cancelling locks cancels all locks back up to the data passed. So if you lock twice and cancel using the first lock, the second lock is ignored
| [in] | cancelToLocation | Which WriteLock() to cancel. |
Definition at line 148 of file SingleProducerConsumer.h.
{
writeAheadPointer=(DataPlusPtr *)cancelToLocation;
}
| bool DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::CheckReadUnlockOrder | ( | const SingleProducerConsumerType * | data | ) | const |
Make sure that the pointer we done reading for the call to ReadUnlock is the right pointer. param[in] A previous pointer returned by ReadLock()
Definition at line 246 of file SingleProducerConsumer.h.
{
return const_cast<const SingleProducerConsumerType *>(&readPointer->object) == data;
}
| void DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::Clear | ( | void | ) |
Definition at line 208 of file SingleProducerConsumer.h.
References _FILE_AND_LINE_, MINIMUM_LIST_SIZE, DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::DataPlusPtr::next, RakNet::OP_DELETE(), and RakAssert.
{
// Shrink the list down to MINIMUM_LIST_SIZE elements
volatile DataPlusPtr *next;
writePointer=readPointer->next;
int listSize=1;
next=readPointer->next;
while (next!=readPointer)
{
listSize++;
next=next->next;
}
while (listSize-- > MINIMUM_LIST_SIZE)
{
next=writePointer->next;
#ifdef _DEBUG
RakAssert(writePointer!=readPointer);
#endif
RakNet::OP_DELETE((char*) writePointer, _FILE_AND_LINE_);
writePointer=next;
}
readPointer->next=writePointer;
writePointer=readPointer;
readAheadPointer=readPointer;
writeAheadPointer=writePointer;
readCount=writeCount=0;
}
| bool DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::ReadIsLocked | ( | void | ) | const |
Returns if ReadUnlock was called before ReadLock
Definition at line 253 of file SingleProducerConsumer.h.
{
return readAheadPointer!=readPointer;
}
| SingleProducerConsumerType * DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::ReadLock | ( | void | ) |
ReadLock must be immediately followed by ReadUnlock. These two functions must be called in the same thread.
| 0 | No data is availble to read |
| Non-zero | The data previously written to, in another thread, by WriteLock followed by WriteUnlock. |
Definition at line 170 of file SingleProducerConsumer.h.
References DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::DataPlusPtr::next.
{
if (readAheadPointer==writePointer ||
readAheadPointer->readyToRead==false)
{
return 0;
}
volatile DataPlusPtr *last;
last=readAheadPointer;
readAheadPointer=readAheadPointer->next;
return (SingleProducerConsumerType*)last;
}
| void DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::ReadUnlock | ( | void | ) |
Signals that we are done reading the the data from the least recent call of ReadLock. At this point that pointer is no longer valid, and should no longer be read.
Definition at line 194 of file SingleProducerConsumer.h.
References RakAssert.
{
#ifdef _DEBUG
RakAssert(readAheadPointer!=readPointer); // If hits, then called ReadUnlock before ReadLock
RakAssert(readPointer!=writePointer); // If hits, then called ReadUnlock when Read returns 0
#endif
readCount++;
// Allow writes to this memory block
readPointer->readyToRead=false;
readPointer=readPointer->next;
}
| int DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::Size | ( | void | ) | const |
This function will estimate how many elements are waiting to be read. It's threadsafe enough that the value returned is stable, but not threadsafe enough to give accurate results.
Definition at line 240 of file SingleProducerConsumer.h.
{
return writeCount-readCount;
}
| SingleProducerConsumerType * DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::WriteLock | ( | void | ) |
WriteLock must be immediately followed by WriteUnlock. These two functions must be called in the same thread.
Definition at line 129 of file SingleProducerConsumer.h.
References _FILE_AND_LINE_, DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::DataPlusPtr::next, and RakAssert.
{
if (writeAheadPointer->next==readPointer ||
writeAheadPointer->next->readyToRead==true)
{
volatile DataPlusPtr *originalNext=writeAheadPointer->next;
writeAheadPointer->next=RakNet::OP_NEW<DataPlusPtr>(_FILE_AND_LINE_);
RakAssert(writeAheadPointer->next);
writeAheadPointer->next->next=originalNext;
}
volatile DataPlusPtr *last;
last=writeAheadPointer;
writeAheadPointer=writeAheadPointer->next;
return (SingleProducerConsumerType*) last;
}
| void DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::WriteUnlock | ( | void | ) |
Definition at line 154 of file SingleProducerConsumer.h.
References RakAssert.
{
// DataPlusPtr *dataContainer = (DataPlusPtr *)structure;
#ifdef _DEBUG
RakAssert(writePointer->next!=readPointer);
RakAssert(writePointer!=writeAheadPointer);
#endif
writeCount++;
// User is done with the data, allow send by updating the write pointer
writePointer->readyToRead=true;
writePointer=writePointer->next;
}
volatile DataPlusPtr* DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::readAheadPointer [private] |
Definition at line 84 of file SingleProducerConsumer.h.
unsigned DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::readCount [private] |
Definition at line 88 of file SingleProducerConsumer.h.
volatile DataPlusPtr* DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::readPointer [private] |
Definition at line 86 of file SingleProducerConsumer.h.
volatile DataPlusPtr* DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::writeAheadPointer [private] |
Definition at line 85 of file SingleProducerConsumer.h.
unsigned DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::writeCount [private] |
Definition at line 88 of file SingleProducerConsumer.h.
volatile DataPlusPtr* DataStructures::SingleProducerConsumer< SingleProducerConsumerType >::writePointer [private] |
Definition at line 87 of file SingleProducerConsumer.h.
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.