I agree that yield and sleep won't solve it reliably - actually, I indicated that in my previous node.
The problem is the space between signaling the main thread and setting eof and the space between testing whether eof is true and waiting on the shared variable. One of these actions needs to be atomic - you don't want to wait for more data if eof is true.
How about this - replace getDataT with this, it'll set $done then signal $sharedData is ready, removing the race condition:
sub getDataT {
my ( $handle, $sharedDataRef, $doneRef ) = @_;
my $temp;
while( !$$doneRef ) {
warn "t-Locking" . $/;
lock $$sharedDataRef;
warn 't-Waiting' . $/;
cond_wait( $$sharedDataRef ) while $$sharedDataRef;
warn 't-Setting' . $/;
$$sharedDataRef = $handle->getline;
# set $done before handing the data over to the main thread
$$doneRef = 1 if $handle->eof;
warn 't-Signalling' . $/;
cond_signal( $$sharedDataRef );
}
return;
}
I would expect that to scale gracefully.
Have you looked at what Thread::Semaphore actually does?
Just the docs. Now I have read the source... point taken ;)