I'm just looking for a review (obvious flaws / ways to improve it) when trying to implement atomic read / write in a structure.
There will be one stream of letters and several streams of reading. The goal is to prevent the reader from having an inconsistent view of the structure without disturbing the writer too much.
I use the atomic primitive fetch-and-add, in this case provided by the Qt framework.
For instance:
OneWriterAtomicState<Point> atomicState;
while(true) {
MyStruct s = atomicState.getState()
s.x += 2; s.y += 2;
atomicState.setState(s);
}
while(true) {
MyStruct s = atomicState.getState()
drawBox(s.x,s.y);
}
Implementation of OneWriterAtomicState:
template <class T>
class OneWriterAtomicState
{
public:
OneWriterAtomicState()
: seqNumber(0)
{
}
void setState(T& state) {
this->seqNumber.fetchAndAddOrdered(1);
this->state = state;
this->seqNumber.fetchAndAddOrdered(1);
}
T getState(){
T result;
int seq;
bool seq_changed = true;
while( (seq=this->seqNumber.fetchAndAddOrdered(0)) & 0x01 || seq_changed ) {
result = this->state;
seq_changed = (this->seqNumber.fetchAndAddOrdered(0)!=seq);
}
return result;
}
private:
QAtomicInt seqNumber;
T state;
}
Here is the second version (memcpy, the reader is inferior, hopefully getState () is fixed):
template <class T>
class OneWriterAtomicState
{
public:
OneWriterAtomicState()
: seqNumber(0)
{
Q_STATIC_ASSERT(!QTypeInfo<T>::isStatic);
}
void setState(T* state) {
this->seqNumber.fetchAndAddOrdered(1);
memcpy(&this->state,state,sizeof(T));
this->seqNumber.fetchAndAddOrdered(1);
}
void getState(T* result){
int seq_before;
int seq_after = this->seqNumber.fetchAndAddOrdered(0);
bool seq_changed = true;
bool firstIteration = true;
while( ((seq_before=seq_after) & 0x01) || seq_changed ) {
if(!firstIteration) {
QThread::yieldCurrentThread();
} else firstIteration = false;
memcpy(result,&this->state,sizeof(T));
seq_after = this->seqNumber.fetchAndAddOrdered(0);
seq_changed = (seq_before!=seq_after);
}
}
bool isInitialized() { return (seqNumber>0); }
private:
QAtomicInt seqNumber;
T state;
} ;
#endif
source
share