Reputation: 23
I am working on a multithreaded VC++ (windows) program that performs some continuous simulation in the main thread. This simulation uses objects that get created in the same thread or in a loader-thread (both can be the case). The same is true for deleting.
I did this so the main thread would not block while very large objects (made up of a lot of other objects) get loaded and unloaded dynamically. This basically worked. But (for example) while the unloader thread is deleting one object after another continuously the new and delete calls of other threads take forever. This seems to be caused by some internal thread protection.
My next move was to reduce the number of new/delete calls by pooling those many smaller objects. So I wrote a primitive memory manager. The manager allocates a 320 MB buffer using malloc() and supplies allocation functionality to the other parts of my program using blocks of 64 bytes. Now I use placement new to create the smaller objects. The manager's alloc/free methods are entirely mutex(lock) protected.
What happens now is that it simply does not work correctly in a multithreading environment. Modifications of the custom managed objects get ignored and so on. I assume what happens is that the entire buffer is viewed as a single variable and as such must not have read/write data races. Is this the case?
Restricting access to one object while an entirely different one gets created/deleted is not an option as you can imagine. So what's the way to go in a situation like this?
Upvotes: 2
Views: 179
Reputation: 23560
The new
s and delete
s are internally synchronizing onto a single Windows Heap-object.
The best solution i know of is using HeapCreate HeapAlloc and HeapFree directly, creating one Heap-object per allocator-thread and each time specifying HEAP_NO_SERIALIZE.
You have to make sure that the thread which allocated is the one which frees, ie you have to "give the memory back" to the allocating helper-thread.
Upvotes: 2
Reputation: 21956
Is this the case?
No, I don't think so. All the memory is just a continuous address space. The CPU's not aware of variables, it only operates pages, cache lines, and bytes.
Possible cause: bugs in your memory manager. Maybe the objects it allocates overlap each other, or maybe you failed the thread synchronization (BTW, you should definitely replace your mutexes with critical sections, see CComAutoCriticalSection and CComCritSecLock ATL classes for convenient whappers - for short operations, they work by order of magnitude faster than mutexes).
Possible cause: bugs in your objects. Maybe your object write an extra byte after its address, but the heap rounded the allocation size so it works OK when each objects is allocated with HeapAlloc win32 API used by new operator.
Possible cause: memory alignment issues. Try aligning addresses of the objects you're allocating at least to 8.
Upvotes: 0