AtomicPointer реализован в levelDb следующим образом:
class AtomicPointer {
private:
void* rep_;
public:
AtomicPointer() { }
explicit AtomicPointer(void* p) : rep_(p) {}
inline void* NoBarrier_Load() const { return rep_; }
inline void NoBarrier_Store(void* v) { rep_ = v; }
inline void* Acquire_Load() const {
void* result = rep_;
MemoryBarrier();
return result;
}
inline void Release_Store(void* v) {
MemoryBarrier();
rep_ = v;
}
};
Теперь я хочу провести некоторый тест, моя цель — проверить атомарную природу AtomicPointer , вот шаг:
1. init структура содержит целые числа
2. один поток увеличивает целые числа на единицу, а другой поток проверяет, что целые числа равны или нет, если нет, сообщают об ошибке.
//thread0 callback
unsigned __stdcall apLoad( void * d)
{
MemoryBarrier();
while (true)
{
B* pb = (B*)ap.Acquire_Load();// B is a struct contains Integer a,b,c
pb->a ++;
pb->b ++;
pb->c ++;
ap.Release_Store((void*)pb);
}
}
//thread1 callback
unsigned __stdcall apStore( void * d)
{
while (true)
{
B* pb = (B*)ap.Acquire_Load();
if(!(pb->a == pb->b && pb->b == pb->c))
{
printf("error : %d-%d-%d\r\n",pb->a,pb->b,pb->c);
}
}
}
//here is the definition of B
typedef struct
{
int a;
int b;
int c;
} B;
У меня вопрос в теме1, как получилось, что он выведет «ошибку»!
Только указатель, предназначенный быть атомарным (не уверен, что он на самом деле без полного кода), содержимое структуры — нет. Если вы изменили указатель — это могла бы быть другая история.
То, что вы намеревались сделать, должно быть сделано по-другому. При текущем размере структуры вам, скорее всего, понадобится блокировка или какая-нибудь интеллектуальная система клонирования (например, запись изменений в копию, а затем сброс указателя для использования этой копии).
Других решений пока нет …