Reputation: 3822
Suppose i have an atomic pointer:
std::atomic<void*> mItems;
and in a function when one thread need to access that, it first check it, and if it is null, thread will allocate memory for it:
void* lItems = std::atomic_load_explicit(&mItems, memory_order_relaxed);
if(lItems == nullptr)
{
void* lAllocation = malloc(...);
if(!std::atomic_compare_exchange_strong_explicit(
&mItems,
&lItems,
lAllocation,
memory_order_relaxed,
memory_order_relaxed))
{
free(lAllocation);
}
}
...
But if N thread run this method concurrency and see mItems
equal to null then all of them will allocate memory and N - 1 of them will free agian.
How i can write similar method with better approach.
Upvotes: 2
Views: 694
Reputation: 153
As I get it, you need that structure as soon as the first thread execute your function, so how about move the allocation before starting any thread? I mean, rearrange the code so that your function is called with the atomic pointer as a parameter, and the structure is allocated before any of the threads calling your function are spawned (you can also avoid creating any thread if the allocation fails)
something like:
std::atomic<void*> mItems;
void func_that_uses_mItems();
int main()
{
mItems = init_struct();
std::thread t1 { &func_that_uses_mItems };
std::thread t2 { &func_that_uses_mItems };
// ... join with or detach threads ...
return( 0 );
}
If the allocation fails an exception is thrown and no thread is started.
Upvotes: 0
Reputation: 67772
I guess you can make the pointer your mutex, using some well-known value (say, the address of a global) as a flag that some other thread is already doing the allocation.
So, your values are: NULL -> magic "allocation in progress" pointer -> real allocation.
The code would do something like:
This way only one thread does the allocation, but your other N-1 threads may be busy waiting. Whether this is really better will vary ...
Upvotes: 1