我只是在尋找反饋(明顯的缺陷/改進方法),試圖在結構上實現原子讀/寫。鎖定自由原子狀態類 - 它是否正確?
將會有一個寫入線程和多個讀取線程。其目的是防止讀者對結構不一致的看法,同時不會妨礙作者太多。
我使用的是獲取和添加原子基元,在這種情況下由Qt框架提供。
例如:
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
謝謝你是的,我看到交錯的問題。但不確定T需要簡單地複製......在這種情況下會出現什麼問題? – greTech 2012-04-18 22:15:13
如果寫入程序線程被pre-mid-T-copy,那麼由於seqNumber檢查,讀者肯定會意識到狀態不一致? – greTech 2012-04-18 22:16:45
@will:例如,如果您有'string'對象,其中複製構造函數必須複製一個內存緩衝區。字符串內部有一個指向內存緩衝區和字符串長度的指針。如果讀者在不一致狀態下看到指針和長度,則複製構造函數可能會導致訪問衝突。 – Timo 2012-04-19 06:14:14