30 Jan 06:18
isValid() on the threadwrapper
Hi ichthyo,
the lumiera thread handle returned by lumiera_thread_run() was initially
meant to be an opaque pointer only notifying the caller about success or
failure of the call. By now we added join() and sync() which gives it
little more purpose. For a joinable thread the handle is guranteed to be
valid until you join it. But for a non joinable thread this handle is
only considerd to be valid until the last sync() call by the thread.
Notably sync/sync_other() must be properly paired and synchronized. This
was only meant for startup synchronization anything beyond this and
perhaps loosing syncronization pairing leads to undefined states. If
such is need then we need some more heavyweight syncronization using a
custom mutex or condition var outside of the scope if the thread
management itself. Whats left is the 'isValid()' call you added to the
thread wrapper which is impossible to implement for non-joinable threads
(by purpose). Argueable this is a bit sloppy, but adding more handshakes
and states there defeats the purpose of a very lightweight threadpool,
each wait is a possible thread-reschedule, each syncronization is a
memory barrier, on SMP systems you want to minimize this.
A possible solution
-------------------
For joinable threads, sync_other() on a thread which is finished and
waits to be joined should raise an error instead (TODO)
sync() in a thread for which there is no matching sync_other() still is
a problem, it will wait forever (the thread heartbeat/lock detector
might detect this and shut down the application).
For non-joinable threads i'd suggest to dispose the thread handle after
a defined number of sync_other() where called. This can be done as
template parameter or as normal construction parameter.
class Thread {
LumieraThread handle;
unsigned dispose_countdown;
Thread (unsigned countdown=0) : dispose_countdown(countdown) ...
~Tread () {REQUIRE(!handle, "not all expected syncs executed");}
sync()
{
if (!handle) throw;
sync_other(handle);
if(!--dispose_countdown) handle = 0;
}
}
in the normal case the threadwraper needs to sync once on its own
behalf, in rare cases the thread creating code might need one (or few)
syncs before the thread is set up. (Btw we may apply this to joinable
threads too, not much of a restriction, of course the handle must be
retained for the join, but excess sync() is a bug)
Anyways syncs must be deterministically paired, the caller must know how
many syncs the threadfunction calls, specifiying that in this way is
likely a good idea.
Christian
_______________________________________________
Lumiera mailing list
Lumiera@...
http://lists.lumiera.org/cgi-bin/mailman/listinfo/lumiera
http://lumiera.org/donations.html
RSS Feed