
On Friday 25 October 2013 16:50:12 you wrote:
On Friday 25 October 2013 14:35:39 Oliver Kowalke wrote:
2013/10/25 Andrey Semashev
That won't work for several reasons. First, as outlined before, you can't store intrusive_ptr in atomic<>. Assuming you store T* instead, then you can't use nullptr as the first argument because CAS accepts it as an lvalue reference. Next, the removal of the pointer is not correct because when CAS fails the pointer is just loaded from the atomic, so you release the pointer and the dangling pointer is left in the array. You have to load e first, then make a loop with CAS and only release if it succeeds and the loaded pointer is not NULL.
array< atomic< T * >, 100 > a{ atomic< T* >( 0) };
That's not correct, it should be:
array< atomic< T * >, 100 > a; for (auto& p : a) p.store(NULL, memory_order_relaxed);
T * desired = new T(); T * expected = 0; if ( a[index].compare_exchange_strong( expected, desired) ) {
// desired added
}
T * expected1 = 0; T * expected2 = 0; if ( ! a[index].compare_exchange_strong( expected1, expected2) ) {
// expected1 is not NULL, expected1 removed == a[index] contains NULL
}
No, that's not right. If compare_exchange_strong returns false, the operation have failed and a[index] != NULL (at least, that's how compare_exchange_strong have left it). It should be:
T* expected = a[index].load(memory_order_acquire); while (!a[index].compare_exchange_weak(expected, NULL, memory_order_release, memory_order_acquire)) { }
if (expected) // The expected value was removed from the array else // The array element was removed by some other thread
Actually, it can be much simpler: T* p = a[index].exchange(NULL); if (expected) // The expected value was removed from the array else // The array element was removed by some other thread