I have this piece of code in my application. I suspect that it is not thread-safe, so decide to ask the SOers.
int * volatile int_ptr;
int count;
Thread 1:
void grow(int new_count)
{
if(new_count <= count) return;
int * new_ptr = new int[new_count];
memset(new_ptr, 0 , new_count * sizeof(int));
memcpy(new_ptr,int_ptr,count);
int * dum_ptr = (int *)InterlockedExchange((volatile long *)&int_ptr,(long)new_ptr)
count = new_count;
delete [] dum_ptr;
}
Thread 2:
int get_value(int index)
{
return int_ptr[index];
}
I know that CRITICAL_SECTION can be used but Thread 1 will work maybe once in a week whereas Thread 2 will work millions of times in a day. In the 99.99999% of the attemps to access the int_ptr, 2nd thread will enter and exit the critical section for nothing. It just does not make sense to me. The application will be working only in Windows 2000 and later with Intel processors obviously with multicores.
Is this code thread-safe? If not, what should I do to make it thread-safe? How can I read int_ptr atomically ? i. e. :
int * dummy_ptr = read_atomic<int *>(int_ptr);
return dummy_ptr[index];
A solution, including std::vector, makes me happier and more comfortable.
No, this is not safe.
get_valuecan read the value ofint_ptr, then get scheduled out. Then another thread can swap outint_ptranddeletethe old value. Whenget_valueis swapped back in, it tries to dereference the value it read fromint_ptr– which has already been deleted.A better approach would be based on “Read-copy-update” (RCU), which has already been used to great effect in Linux. The basic principle is that you don’t delete the old value right away – you wait until some point in time when you can be conservatively sure that nothing still has the old pointer value, then delete it.
Unfortunately, there’s no RCU library implementation on Windows yet. You could try porting urcu to Windows though, I suppose.