<div dir="ltr">Thanks Christof, that's very helpful. <div><br></div><div>iain</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Oct 24, 2020 at 5:53 PM Christof Ressi <<a href="mailto:info@christofressi.com">info@christofressi.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  
    
  
  <div>
    <p>But if you're still worried, creating a pool of objects of the
      same size is actually quite easy, just use a
      <a href="https://en.wikipedia.org/wiki/Free_list" target="_blank">https://en.wikipedia.org/wiki/Free_list</a>.</p>
    <p>Christof<br>
    </p>
    <div>On 25.10.2020 02:45, Christof Ressi
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <p> </p>
      <blockquote type="cite">
        <div>A) Am I right, both about being bad, and about clock
          pre-allocation and pooling being a decent solution?</div>
        <div>B) Does anyone have tips on how one should implement and
          use said clock pool?</div>
      </blockquote>
      ad A), basically yes, but in Pd you can get away with it. Pd's
      scheduler doesn't run in the actual audio callback (unless you run
      Pd in "callback" mode) and is more tolerant towards operations
      that are not exactly realtime friendly (e.g. memory allocation,
      file IO, firing lots of messages, etc.). The audio callback and
      scheduler thread exchange audio samples via a lockfree ringbuffer.
      The "delay" parameter actually sets the size of this ringbuffer,
      and a larger size allows for larger CPU spikes.
      <p>In practice, allocating a small struct is pretty fast even with
        the standard memory allocator, so in the case of Pd it's nothing
        to worry about. In Pd land, external authors don't really care
        too much about realtime safety, simply because Pd itself doesn't
        either.<br>
      </p>
      <p>---<br>
      </p>
      <p>Now, in SuperCollider things are different. Scsynth and
        Supernova are quite strict regarding realtime safety because DSP
        runs in the audio callback. In fact, they use a special realtime
        allocator in case a plugin needs to allocate memory in the audio
        thread. Supercollider also has a seperate non-realtime thread
        where you would execute asynchronous commands, like loading a
        soundfile into a buffer.</p>
      <p>Finally, all sequencing and scheduling runs in a different
        program (sclang). Sclang sends OSC bundles to scsynth, with
        timestamps in the near future. Conceptually, this is a bit
        similar to Pd's ringbuffer scheduler, with the difference that
        DSP itself never blocks. If Sclang blocks, OSC messages will
        simply arrive late at the Server.<br>
      </p>
      <p>Christof<br>
      </p>
      <div>On 25.10.2020 02:10, Iain Duncan
        wrote:<br>
      </div>
      <blockquote type="cite">
        
        <div dir="ltr">Hi folks, I'm working on an external for Max and
          PD embedding the S7 scheme interpreter. It's mostly intended
          to do things at event level, (algo comp, etc) so I have been
          somewhat lazy around real time issues so far. But I'd like to
          make sure it's as robust as it can be, and can be used for as
          much as possible. Right now, I'm pretty sure I'm being a bad
          real-time-coder. When the user wants to delay a function call,
          ie  (delay 100 foo-fun), I'm doing the following:
          <div><br>
          </div>
          <div>- callable foo-fun gets registered in a scheme hashtable
            with a gensym unique handle</div>
          <div>- C function gets called with the handle</div>
          <div>- C code makes a clock, storing it in a hashtable (in C)
            by the handle, and passing it a struct (I call it the "clock
            callback info struct") with the references it needs for it's
            callback</div>
          <div>- when the clock callback fires, it gets passed a void
            pointer to the clock-callback-info-struct, uses it to get
            the cb handle and the ref to the external (because the
            callback only gets one arg), calls back into Scheme with
            said handle</div>
          <div>- Scheme gets the callback out of it's registry and
            executes the stashed function</div>
          <div><br>
          </div>
          <div>This is working well, but.... I am both allocating and
            deallocating memory in those functions: for the clock, and
            for the info struct I use to pass around the reference to
            the external and the handle. Given that I want to be
            treating this code as high priority, and having it execute
            as timing-accurate as possible, I assume I should not be
            allocating and freeing in those functions, because I could
            get blocked on the memory calls, correct? I think I should
            probably have a pre-allocated pool of clocks and their
            associated info structs so that when a delay call comes in,
            we get one from the pool, and only do memory management if
            the pool is empty. (and allow the user to set some
            reasonable config value of the clock pool). I'm thinking RAM
            is cheap, clocks are small, people aren't likely to have
            more than 1000 delay functions running concurrently or
            something at once, and they can be allocated from the init
            routine.</div>
          <div><br>
          </div>
          <div>My questions:</div>
          <div>A) Am I right, both about being bad, and about clock
            pre-allocation and pooling being a decent solution?</div>
          <div>B) Does anyone have tips on how one should implement and
            use said clock pool?</div>
          <div><br>
          </div>
          <div>I suppose I should probably also be ensuring the Scheme
            hash-table doesn't do any unplanned allocation too, but I
            can bug folks on the S7 mailing list for that one...</div>
          <div><br>
          </div>
          <div>Thanks!</div>
          <div>iain</div>
        </div>
        <br>
        <fieldset></fieldset>
        <pre>_______________________________________________
Pd-dev mailing list
<a href="mailto:Pd-dev@lists.iem.at" target="_blank">Pd-dev@lists.iem.at</a>
<a href="https://lists.puredata.info/listinfo/pd-dev" target="_blank">https://lists.puredata.info/listinfo/pd-dev</a>
</pre>
      </blockquote>
      <br>
      <fieldset></fieldset>
      <pre>_______________________________________________
Pd-dev mailing list
<a href="mailto:Pd-dev@lists.iem.at" target="_blank">Pd-dev@lists.iem.at</a>
<a href="https://lists.puredata.info/listinfo/pd-dev" target="_blank">https://lists.puredata.info/listinfo/pd-dev</a>
</pre>
    </blockquote>
  </div>

_______________________________________________<br>
Pd-dev mailing list<br>
<a href="mailto:Pd-dev@lists.iem.at" target="_blank">Pd-dev@lists.iem.at</a><br>
<a href="https://lists.puredata.info/listinfo/pd-dev" rel="noreferrer" target="_blank">https://lists.puredata.info/listinfo/pd-dev</a><br>
</blockquote></div>