Я хотел бы свести к минимуму синхронизацию и писать код без блокировки, когда это возможно, в моем проекте. Когда абсолютно необходимо, я бы хотел заменить легкие шпильки, построенные из атомных операций для блокировок mutex для pthread и win32. Я понимаю, что это системные вызовы под ним и могут вызвать контекстный переключатель (что может быть ненужным для очень быстрых критических секций, где было бы предпочтительнее просто крутить несколько раз).
Атомные операции, о которых я говорю, хорошо описаны здесь: http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Atomic-Builtins.html
Вот пример, иллюстрирующий то, о чем я говорю. Представьте себе RB-дерево с несколькими читателями и писателями. RBTree:: exists() доступен только для чтения и потокобезопасен, RBTree:: insert() потребует исключительного доступа одним автором (и без чтения), чтобы быть в безопасности. Некоторый код:
class IntSetTest
{
private:
unsigned short lock;
RBTree<int>* myset;
public:
// ...
void add_number(int n)
{
// Aquire once locked==false (atomic)
while (__sync_bool_compare_and_swap(&lock, 0, 0xffff) == false);
// Perform a thread-unsafe operation on the set
myset->insert(n);
// Unlock (atomic)
__sync_bool_compare_and_swap(&lock, 0xffff, 0);
}
bool check_number(int n)
{
// Increment once the lock is below 0xffff
u16 savedlock = lock;
while (savedlock == 0xffff || __sync_bool_compare_and_swap(&lock, savedlock, savedlock+1) == false)
savedlock = lock;
// Perform read-only operation
bool exists = tree->exists(n);
// Decrement
savedlock = lock;
while (__sync_bool_compare_and_swap(&lock, savedlock, savedlock-1) == false)
savedlock = lock;
return exists;
}
};
(предположим, что это не должно быть безопасным исключением)
Является ли этот код действительно потокобезопасным? Есть ли какие-либо плюсы и минусы этой идеи? Любой совет? Является ли использование спинлоков подобным образом плохой идеей, если потоки не являются действительно параллельными?
Спасибо заранее.;)