Deep dive into threading, blocking, sync/async, scheduler internals (split from scztt quarks thread)

After mulling this over, I agree with you (and James Harkins) now that there’s
duck-type-based hidden class in the hierarchy that splits streams into
those that can usefully go on a clock and those that can’t because they
don’t conform to the clock protocol, which is embedded in the operating
assumptions of some sclang synchronization primitives, like CondVar or Condition.)

So the real hierarchy in sclang, taking that into account is at least something like

Stream--[ClockStream]--PauseStream(wraps a ClockStream arg)

PauseStream isn’t exactly useful at wrapping a “pure” stream unless that wrapped stream is of this hidden ClockStream class. So when I wrote (a whole bunch of posts before) this example, which I’m slightly simplifying here

f = FuncStream { "Hi!!!".postln; 0.2 }
p = PauseStream(f, AppClock).play
p.pause // stops it
p.resume // resumes it

It works because FuncStream { "Hi!!!".postln; 0.2 } is actually of this
duck-typed, undeclared ClockStream class.

I also agree now that the bugs that I had reported against FlowVar, Condition, and CondVar aren’t really so (so I closed them) because it is indeed expected, although alas not explicitly documented, that these classes get run from a Routine that only runs on a clock, not just any kind of Routine. So, really the hierarchy is more like

Stream--[ClockStream]--PauseStream
 \            \ 
  \            \ 
   \---Routine--[ClockOnlyRoutine]

While one can write “mixed” routines that can even tell the difference when they run a clock and when they don’t, that approach isn’t really supported by most parts of the class library. It wasn’t exactly obvious to me though that that must necessarily be the case.

And to add to the sclang gotchas repertoire, EventStreamPlayer is a bit more demanding of
the ClockStream multiplexed into dur and in the underlying delta too, which seems to the lowest-level field that clock timing translates to in the Event business), namely it won’t accept a self-pausing dur or even such a delta stream, i.e. one with symbols in it.

Pbind(\delta, Pseq([1, 2, \hang, 1])).play
// ^^ The preceding error dump is for ERROR: Primitive '_Event_Delta' failed. Wrong type.

So additionally:

Stream--[ClockStream]--[NonSelfPausingClockStream == NumberStream]

And EventStreamPlayer only accepts the last kind for its dur or even delta sub-stream.


By the way, I’ve recently realized you’re the main dev of the Python sc3 package, so that explains why you’re not reading sclang help much nowadays :slight_smile: