You are not logged in.
I'm having a hard time figuring out how to manage deallocation of memory in multithreaded environments. Specifically what I'm having a hard time with is using a lock to protect a structure, but when it's time to free the structure, you have to unlock the lock to destroy the lock itself. Which will cause problems if a separate thread is waiting on that same lock that you need to destroy.
I'm trying to come up with a mechanism that has retain counts, and when the object's retain count is 0, it's all freed. I've been trying a number of different things but just can't get it right. As I've been doing this it seems like you can't put the locking mechanism inside of the structure that you need to be able to free and destroy, because that requires you unlock the the lock inside of it, which could allow another thread to proceed if it was blocked in a lock request for that same structure. Which would mean that something undefined is guaranteed to happen - the lock was destroyed, and deallocated so either you get memory access errors, or you lock on undefined behavior..
Would someone mind looking at my code? I was able to put together a sandboxed example that demonstrates what I'm trying without a bunch of files.
Thanks for any help!
Yeah, if you're dealing with a dynamically allocated object which can go away at any time, you certainly don't want to put your lock inside it... What you want the lock to protect is actually accessing the pointer to that object... So, the lock needs to be outside, and be persistent (ie: not dynamically allocated and freed along with the object itself)... That way, no one will ever dereference the pointer to the object at all unless they hold the lock... In the case of removing the object, any other threads trying to aquire the lock after you've begun the removal process will see that the pointer to the object is now NULL once they finally do aquire the lock, so they'll know it has been removed...
What you have to keep in mind is what a lock actually protects against.
If you have a structure lock, that lock protects against concurrent access
to the structure. It can only do lifetime management indirectly, such as
updating a reference count. But as Rob said, you need another lock to
serialize access to all the pointers leading to the structure. In your case,
you need to take another lock for any container modifications (I guess,
your code is a bit fuzzy. Normally you have some kind of list/tree or other
data structure to store all references to dynamic structures). When you
hold that lock AND the structure lock, it's safe to remove any references
to the structure and deallocate it.
So I guess what makes it hard is to try to do everything with one structure
lock, which is in the wrong place for this. If you don't have a container,
but a linked list with the next and previous pointers within the structure
itself, you can get away by taking the previous, current and next structure
locks (in a fixed order, to avoid deadlock) and update all the pointers and
deallocate safely, without introducing new locks. But it gets quite messy
when using too many wrapper containers like in your example code.