By the way, if i change (system* "sleep" "1s") to the (system* "true"), nothing changes. The log of execution is the same:
$ guile test.scm M: (sleep 3) M: protocol exchange M: new sleep thread M: (sleep 3) R: Going to (sleep 1) R: sleep-loop finished M: protocol exchange M: (sleep 3) M: protocol exchange M: (sleep 3) But 3 seconds are more than enough to finish the work thread and pull the state down to the #:nothing-to-do, which should cause the main thread re-run work thread. - MB. Respectfully On Sat, Sep 22, 2018 at 09:39:38AM +0500, Михаил Бахтерев wrote: > On Fri, Sep 21, 2018 at 05:26:27PM -0400, Mark H Weaver wrote: > > Hi, > > > > Can you describe in more detail the behavior you are seeing? What > > messages do you see on stderr from your 'dump' calls when it gets stuck? > > What state is the atomic box left in? > > > > I see a couple of problems with the code below: > > > > * Two threads write concurrently to the same port, namely > > (current-error-port). You should use thread synchronization to ensure > > that operations to a given port are serialized. > > > > * There's a race condition when the atomic box is in the #:accepted > > state. If the main thread finds the box in that state, it changes the > > state to #:need-to-sleep, which will apparently cause the other thread > > to sleep again. > > > > I'm not sure if these problems could explain what you're seeing. > > > > Regards, > > Mark > > > > The code is supposed to model the following behaviour. > > The main thread tracks some events (in the example: the end of (sleep > 3)). If one or multiple events occurred some long-lasting external > command should be executed. Long-lasting means that multiple events may > occur during execution. > > To perform that the main thread should: > > 1. either to run new work thread (sleep-loop procedure), which will > call (system* ...); > > 2. or to communicate the fact of events occurrences to the work > thread, which is supposed to detect this and just repeat the command. > > If multiple events have occurred during command execution the command > should be re-executed only once. > > The event occurrence is communicated through simple protocol with three > states: #:nothing-to-do < #:accepted < #:need-to-sleep. The main thread > pulls state up, and work thread pulls it down. When the main thread > detects event, and the state is #:accepted, it means, that work thread > accepted the previous job, and executing it now, so the main thread > pulls the state up to need-to-sleep, and the work thread re-executes > command (sleeps again in the test case), when the previous external > command run has finished. This is intended behaviour. > > I expect the program to print some garbage, showing that work thread is > restarted periodically. Something like that (it is result of using > (sleep 1) instead of (system* "sleep" "1s")): > > $ guile test.scm > M: (sleep 3) > M: protocol exchange > M: new sleep thread > M: (sleep 3) > > R: Going to (sleep 1) > R: sleep-loop finished > M: protocol exchange > M: new sleep thread > M: (sleep 3) > : (sleep 3)R: Going to (sleep 1) > > R: sleep-loop finished > M: protocol exchange > M: new sleep thread > M: (sleep 3) > > R: Going to (sleep 1) > R: sleep-loop finished > M: protocol exchange > M: new sleep thread > M: (sleep 3) > > : (sleep 3)R: Going to (sleep 1) > R: sleep-loop finished > > But what i get with (system* "sleep" "1s") is this: > > $ guile test.scm > M: (sleep 3) > M: protocol exchange > M: new sleep thread > M: (sleep 3) > R: Going to (sleep 1) > R: sleep-loop finished > M: protocol exchange > M: (sleep 3) > M: protocol exchange > M: (sleep 3) > M: protocol exchange > M: (sleep 3) > > So, the state of the atomic-box is stuck in #:need-to-sleep somehow. > > - MB. Respectfully