Re: To thread or not to thread ?
Lourens Veen wrote:
Why not use C++' exception mechanism to cancel threads? The owner of a
thread object (or handle or reference or whatever) calls a cancel()
function which causes a thread_cancelled exception to be thrown in
that thread. Then cleanup can happen by the normal exception
handlers.
It seems from a quick web search that this idea is obvious enough that
it's been at least tried before. I can see a problem with throw()
declarations becoming somewhat less of a guarantee, and there would
have to be a very careful specification of at which points the
exception would become visible. Perhaps it would even be useful to
have atomic blocks that would execute fully before the exception
became visible if it were thrown halfway. If any kind of jumping or
looping would be disallowed inside an atomic block, the exception
would eventually be thrown.
I haven't thought this through properly, so maybe there's something
obvious I'm missing, but it seems logical.
By doing so, you would implicitly stipulate that exceptions can be
thrown asynchronously, meaning that the thread can be interrupted no
matter what it is doing, at any point in time. This would amount to
rogue termination under the guise of the normalcy of protection, and
rogue termination is possible now. Even operator new() with its
ubiquity and potential to throw bad_alloc(), provides mechanism for
predictability and order - it will not cause an exception to be thrown
at "any point in time", say, half-way through modifying a global
structure.
If it is required that a thread cannot be interrupted "at any point in
time", but at a "well known check point", then those points would have
to be interspersed in the code everywhere by the compiler to support
expedient cancellation. If you allow that, one could argue that you
should allow the programmer to use the flag testing technique that John
Q mentioned. But if you allow flag testing, not only do you have to
keep testing "everywhere", setting up the flag to be tested under each
execution scenario, you essentially implement a
execute-real-code-plus-execute-spin-on-semaphore situation, where
checking the flag involves use of CPU cycles to test the flag.
And then the problem becomes clear:
The requirement of abrupt termination means that the canceled thread
must not wait too long to check its flag. But if it is not to wait to
long, that means it must spend much time checking the flag, which is
extremely wasteful, especially in times when it has nothing else to do.
More importantly in the nothing-else-to-do-but-check-flag situation,
you would have to determine the "optimal" "inter-wait duration" for
checking the "time-to-die" flag. You will wonder if 1 second is
enough. You will wonder if 5 seconds is enough. You will see that in
certain cases, 100 milliseconds is absolutely positively too much. And
you will have to have this conversation with yourself each and every
time you use this method.
With events, there is no waste in time, and there is no ambiguity about
"when to check". The thread to be canceled can block indefinitely and
know that it will not have to worry about dying promptly at the behest
of another thread, because triggering of the event by the external
thread will result in immediate unblocking. You simply right your code
(pun intended), and let the kernel-mode machinery do what it is best
at.
-Le Chaud Lapin-
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]