Hi all,
It must be time for another multitasking related question :-)
Let's assume I have an inheritable 'Lockable' class that under AmigaOS wraps a SignalSemaphore. It provides methods such as tryLock() and waitLock() that respectively wrap AttemptSemaphore() and ObtainSemaphore() etc.
All well and good so far. However there is one implementation issue on AmigaOS that nags me slightly.
Let's assume we have three threads that want to lock the object, which has been allocated on the free store and ultimately must be deleted. Deleting can only be achieved by obtaining an exclusive lock first, which is hidden away inside the destructor; that is to say, the implelemtation of ~Lockable() does an ObtainSemaphore()/ReleaseSemaphore() internally as part of te clean up.
Lets start by assuming thread 1 currently has ownership and is busy with it.
In the meantime, thread 2 deletes the object, which causes it to wait for ownership (by virtue of the destructor implementation).
In most cases this is fine. Thread 1 will eventually finish with the object and as soon as thread 2 gets it, it is deleted, no harm no foul.
However, lets assume in this case, a third thread attempts to lock the object while thread 1 still has ownership and thread 2 has already got in the queue ahead of it.
Thread 2 comes next and destroys the object. As the destructor finishes up, it ReleaseSemaphore()'s which means that thread 3 is suddenly signalled that it now has possesion.
This was a problem that I wrote a kludge for. The destructor unwinds any pending locks, setting a flag in each calling task that informed it the object was unavailable causing their calles to waitLock() to return a particular error, after which it is totally illegal to access the object (as it no longer exists).
However this is extremely dirty as I am effectively force unwinding all the calls to ObtainSemaphore() (by repeating a ReleaseSemaphore() until no locks are pending) made by other threads in the thread that is destroying the object.
Whilst it prevents the other threads from getting a lock on someting which no longer exists, ensures they are woken up again and ensures all the calls to ObtainSemaphore() are closed, I am sure this is illegal or at the very least extremely bad style.
Is there a better way or indeed a de facto way of dealing with objects that may be deleted whilst other tasks are waiting for them that ensures those threads simply dont wait forever?
-edit-
I should point out that I don't actually write code that would cause these types of conditions to occur, but I want to ensure that if someone ever did the system copes with it as sensibly as possible.