
On Mar 27, 2007, at 11:47 AM, Peter Dimov wrote:
join() { // Don't want to pretend to join with non-existent // (or detached) thread, make noise if (handle_ == 0) throw ?; while (!tl->done) tl->cv1.wait(); detach(); // point of contention with N2178, makes join non- const, // and disables multi-join. Without it, resources not // released until explicit detach() or ~thread() }
... we can still remove this detach() call from join() and the user is free to get the old semantics back by just calling detach() explicitly after join() (whereas the reverse is not true).
Ok, I'm still having pain from realloc doing too much. :-) Maybe this is a safe spot to tweak the pthreads semantics since ~thread() *must* catch any leaks and C doesn't have that option. I've tweaked the pseudo code as below and am continuing to look for problems with it. I believe this comes closer to Anthony's earlier post. And note the const qualifier I put on join!!! :-) (reserving the right to waffle back...) pthread_t handle_; thread_local_data* tl; detach() { // If has already been detached, that means tl may already be released // therefore not safe to go through twice. // But maybe ok to ignore subsequent detach? if (handle_ != 0) { tl->wait_on_owner = false; tl->cv2.notify_all(); handle_ = 0; } } cancel() { // Canceling a non-existent thread seems harmless if (handle_ != 0) tl->cancel_pending = true; } join() const { // Don't want to pretend to join with non-existent // (or detached) thread, make noise if (handle_ == 0) throw ?; while (!tl->done) tl->cv1.wait(); } thread::id get_id() const {return thread::id(handle_);} ~thread() { cancel(); // harmless if already canceled detach(); // harmless if already detached } start() { allocate_all_resources(); // tl != 0 tl->done = false; tl->wait_on_owner = true; tl->cancel_pending = false; try { f(); } catch (thread_canceled&) { } catch (...) { terminate(); } tl->done = true; tl->cv1.notify_all(); while (tl->wait_on_owner) tl->cv2.wait(); release_all_resources(); // tl = 0 } -Howard