我只是在尝试在结构上实现原子读/写时寻找反馈(明显的缺陷/改进方法)。
将有一个写入线程和多个读取线程。目的是防止读者对结构有不一致的看法,同时又不会过多地妨碍作者。
我正在使用 fetch-and-add atomic 原语,在这种情况下由 Qt 框架提供。
例如:
/* global */
OneWriterAtomicState<Point> atomicState;
/* Writer */
while(true) {
MyStruct s = atomicState.getState()
s.x += 2; s.y += 2;
atomicState.setState(s);
}
/* Reader */
while(true) {
MyStruct s = atomicState.getState()
drawBox(s.x,s.y);
}
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;
/* repeat while seq is ODD or if seq changes during read operation */
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;
}
这是第二版(memcpy,读者屈服,希望修复 getState() ):
template <class T>
class OneWriterAtomicState
{
public:
OneWriterAtomicState()
: seqNumber(0)
{
/* Force a compile-time error if T is NOT a type we can copy with memcpy */
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;
/* repeat while seq_before is ODD or if seq changes during read operation */
while( ((seq_before=seq_after) & 0x01) || seq_changed ) {
/* Dont want to yield on first attempt */
if(!firstIteration) {
/* Give the writer a chance to finish */
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 // ONEWRITERATOMICSTATE_H