简体   繁体   中英

Error with function in multithreaded environment

What my function does is iterate through an array of bools and upon finding an element set to false, it is set to true. The function is a method from my memory manager singleton class which returns a pointer to memory. I'm getting an error where my iterator appears to loop through and ends up starting at the beginning, which I believe to because multiple threads are calling the function.

void* CNetworkMemoryManager::GetMemory()
{
        WaitForSingleObject(hMutexCounter, INFINITE);

    if(mCounter >= NetConsts::kNumMemorySlots)
    {
       mCounter = 0;
    }

    unsigned int tempCounter = mCounter;

    unsigned int start = tempCounter;

    while(mUsedSlots[tempCounter])
    {
        tempCounter++;

        if(tempCounter >= NetConsts::kNumMemorySlots)
        {
            tempCounter = 0;
        }

        //looped all the way around
        if(tempCounter == start)
        {
            assert(false);
            return NULL;
        }
    }

    //return pointer to free space and increment

    mCounter = tempCounter + 1;
        ReleaseMutex(hMutexCounter);

    mUsedSlots[tempCounter] = true;
    return mPointers[tempCounter];
}

My error is the assert that goes off in the loop. My question is how do I fix the function and is the error caused by multithreading?

Edit: added a mutex to guard the mCounter variable. No change. Error still occurs.

I can't say if the error is caused by multi threading or not but I can say your code is not thread safe.

You free the lock with

ReleaseMutex(hMutexCounter);

and then access tempCounter and mUsedSlots:

mUsedSlots[tempCounter] = true;
return mPointers[tempCounter];

neither of which are const. This is a data race because you have not correctly serialized access to these variables.

Change this to:

mUsedSlots[tempCounter] = true;
const unsigned int retVal = mPointers[tempCounter];
ReleaseMutex(hMutexCounter);
return retVal;

Then at least your code is thread safe, whether this solves your problem I can't say, try it out. On machines with multiple cores very weird things to happen as a result of data races.

As general best practice I would suggest looking at some C++11 synchronization features like std::mutex and std::lock_guard , this would have saved you from your self because std::lock_guard releases that lock automatically so you can't forget and, as in this case, you can't do it too soon inadvertently. This would also make your code more portable. If you don't have C++11 yet use the boost equivalents.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM