I see that my approach has been totally bum-over-tits so I consider this case closed :)
Hm. Just because the initial approach is bad, it doesn't mean that the over all goal is unobtainable.
Eg. This almost does what you asked for (note the Inline::C bit is only to get accurate timings; it doesn't affect what the code does):
#! perl -slw
use strict;
use Inline C => Config => BUILD_NOISY => 1;
use Inline C => <<'END_C', NAME => 'rdtsc', CLEAN_AFTER_BUILD => 0;
SV *rdtsc() {
return newSVuv( (UV)__rdtsc() );
}
END_C
use threads;
use threads::shared;
my $sig:shared;
my $l0 :shared;
my $l1 :shared;
my $ts :shared = 0;
async( sub {
my $lockRef = shift;
my $tid = threads ->tid;
while( 1 ) {
printf "[%5d] Waiting at: %10u ms\n", $tid, ( rdtsc() - $ts
+ ) / 2400;
{
lock $$lockRef;
cond_wait( $sig, $$lockRef );
}
printf "[%5d] Got signal at: %10u ms\n", $tid, ( rdtsc() - $ts
+ ) / 2400;
}
}, $_ )->detach for \$l0, \$l1;
sleep 1; ## Give threads a chance to start.
while( 1 ) {
{ lock $ts; $ts = rdtsc() };
printf "[main] signalling at: %10u\n", 0;
{ lock $sig; cond_broadcast( $sig ) };
sleep 3;
}
__END__
C:\test>cond_b.pl
[ 1] Waiting at: 7250756853 ms
[ 2] Waiting at: 7250765890 ms
[main] signalling at: 0
[ 2] Got signal at: 1422 ms
[ 1] Got signal at: 1426 ms
[ 2] Waiting at: 3361 ms
[ 1] Waiting at: 6105 ms
[main] signalling at: 0
[ 2] Got signal at: 1384 ms
[ 1] Got signal at: 1398 ms
[ 2] Waiting at: 3695 ms
[ 1] Waiting at: 7011 ms
[main] signalling at: 0
[ 2] Got signal at: 1362 ms
[ 1] Got signal at: 1361 ms
[ 2] Waiting at: 3672 ms
[ 1] Waiting at: 7077 ms
Terminating on signal SIGINT(2)
NB: ms above is microseconds!
But note that even on my 4 core system, the 2 threads do not see the signal at exactly the same time. (also, if you leave it running, you'll see one of the limitations (a.k.a total idiocies) of the cond_var mechanism.
But that brings me back to the questions I alluded to earlier. Why have your main thread attempt to coordinate starting two other threads; and then just sit there doing nothing? Ie, why use 3 threads?
I can see that you might need to run the recorder and player from different threads, but why not: main: start recorder thread;
main: start player (in main);
main: wait for player to finish;
main: signal recorder thread to stop.
This mirrors what you'd do manually. Switch the recorder on; switch the player on; when the player finishes; switch the recorder off.
There is plenty of scope for solving the problem; you just need to tackle it the right way.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
|