I have designed template classes OwnedObjectVector and OwnedObjectSet, which I am using to maintain ownership of allocated objects. I've done this so that in the case of an exception being thrown, and the destructor being called on OwnedObjectVector, the allocated objects can be freed safely.
Since I am using an ordinary std::vector and std::set in the implementation, I have wrapped my accesses with a mutex. The question which arises however, is whether or not a destructor should use a mutex to access the internal data structures. This is something I need advice on... does it make sense that a destructor should use a mutex?
What if the destructor is called, while other functions are waiting for the mutex? Is that even possible? Is it possible somehow that there is a mutexed call right after the call to the destructor?
What will generally happen with exceptions in TBB code? For example, suppose that a class has multiple executing functions, and one of them throws an exception. What will happen to the other function calls? This is a larger question, which I suspect has already been answered on the forum. I'll search around for an answer to this one.
Currently, the task scheduler is not exception-safe. This is something we are currently fixing. Until then, method execute() in a task, or methods of a loop body object should not let exceptions escape.
The rest of your questions need more specific examples/code fragments to answer. In general, I'd be suspicious if destruction of an object must be protected by a mutex, because any other thread waiting to access said object is going to see it in an invalid state. However, if the destructor invokes non-thread-safe operations, then it should be using a mutex. But the mutex should be the one protecting those non-thread-safe operations, not protecting the object.
How will the destructor in general behave in a TBB application? For instance, is it possible for a destructor to be called while:
- A member function is executing?
- Other functions are waiting for a mutex within a class, while the destructor is being called?
- Could some form of race condition be created because of destructor calls?
In the original example I posted, I mentioned that I have ownership classes (these just hold pointers to objects, and the destructor frees memory of the objects) that are able to be accessed concurrently. Suppose that multiple TBB tasks have called a function takeOwnership(Something* object), which passes ownership of the object to the ownership class instance. This function internally adds the pointer to a vector or set, but suppose a bad allocation exception is thrown. In this case, the destructor is going to be called while other TBB tasks are accessing the class.
This example is particular to my application, however there are likely other examples which could raise the same question.
The behviour in this case could be for a running TBB task that catches an unhandled exception to terminate all related TBB tasks, and throw another exception. I'm not entirely sure in my case how I could cleanly detect concurrent accesses to an object that is being destructed.
I'm having a little trouble visualizing your example. Is Ownership exclusive? Or are these just links? (Can an object be owned by multiple tasks?). When the bad allocation exception is thrown, is it the objects that need to be culled or the ownership list?Are bad allocation exceptions a common, recoverable path, or a catastrophic one?