<div dir="ltr"><div>Hi Iain,</div><div><br></div><div>Interesting problem and I&#39;d be interested to see any input from others.</div><div>I had the same problem in my VST3 scenario: the gui and the dsp run on separate threads!</div><div><br></div><div>How I tackled this was with 2 separate s7 instances and they exchange messages.</div><div>The messages are stored in the c++ application instance in an std::queue&lt;std::string&gt;</div><div><br></div><div>The dsp instance has the following c function bound to emit messages<br></div><div><br></div><div>// the emit accepts a list with symbols,numbers etc.</div><div>// the car could be your message type and then the data would follow<br></div><div>s7_pointer s7vst::dsp_emit(s7_scheme* sc, s7_pointer args) {</div><div>    // the s7 instance holds in *app* the pointer of the relevant application object<br></div><div>    s7vst* that = (s7vst*) s7_c_pointer(s7_name_to_value(sc, &quot;*app*&quot;));<br><br>    s7_pointer msg = s7_car(args);<br>    std::string msg_str = s7_format(sc, s7_list(sc, 3,<br>                                    s7_f(sc),<br>                                    s7_make_string(sc, &quot;~A\n&quot;),<br>                                    msg<br>                                               ));<br>    std::unique_lock lock(that-&gt;dsp_msg_mutex);<br>    that-&gt;dsp_messages.push(msg_str);<br>    return s7_nil(sc);<br>}</div><div><br></div><div><br></div><div>And then, the gui instance has a &quot;recv&quot; function and acts upon any received messages<br></div><div><br></div><div>s7_pointer s7vst::gui_recv(s7_scheme* sc, s7_pointer args) {<br>    s7vst* that = (s7vst*) s7_c_pointer(s7_name_to_value(sc, &quot;*app*&quot;));<br>    while (!that-&gt;dsp_msg_mutex.try_lock()) {<br>        cerr &lt;&lt; &quot;Gui recv: could not lock!&quot;;<br>        std::this_thread::sleep_for(std::chrono::milliseconds(10));<br>    }<br><br>    if (that-&gt;dsp_messages.empty()) {<br>        that-&gt;dsp_msg_mutex.unlock();<br>        return s7_nil(sc);<br>    }<br>    s7_pointer msg_vector = s7_make_vector(sc, that-&gt;dsp_messages.size());<br>    size_t pos = 0;<br>    while (!that-&gt;dsp_messages.empty()) {<br>        std::string msg = that-&gt;dsp_messages.front();<br>        that-&gt;dsp_messages.pop();<br>        s7_pointer port = s7_open_input_string(sc, msg.c_str());<br>        s7_pointer obj = s7_read(sc, port);<br>        s7_close_input_port(sc, port);<br>        s7_vector_set(sc, msg_vector, pos, obj);<br>        pos++;<br>    }<br><br>    that-&gt;dsp_msg_mutex.unlock();<br><br>    return msg_vector;<br>}</div><div><br></div><div>At least that&#39;s a quick &amp; dirty way that I got it working.</div><div>Sorry for the long snippets.</div><div><br></div><div>Hope it&#39;s of help<br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 25 Sep 2020 at 03:41, Iain Duncan &lt;<a href="mailto:iainduncanlists@gmail.com">iainduncanlists@gmail.com</a>&gt; 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 dir="ltr">Another option I&#39;m thinking of is giving the users a way to expressly send messages to one or the other thread within the object (ie by requesting promote or defer) and then letting them protect the data sensibly themselves. I&#39;m not sure how this is normally done in Scheme though.<div><br></div><div>iain</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Sep 24, 2020 at 6:34 PM Iain Duncan &lt;<a href="mailto:iainduncanlists@gmail.com" target="_blank">iainduncanlists@gmail.com</a>&gt; 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 dir="ltr">Hi folks, I&#39;m hoping someone can help me out with a question around S7.<div><br></div><div>In Max/MSP, when setup for live use there are (generally) two threads of operation, with the high-priority/dsp thread able to interrupt the low/GUI. If one doesn&#39;t do anything special, this means a max external (such as my Scheme-for-Max) could be receiving messages in both: low for things originating from a GUI action, high from metronomes or midi input.  I assume that I should not expect all to be ok if I have one instance of an s7 interpreter, which could be accessed from either thread, and it could get interrupted part way through an eval operation to run another eval in another thread that may access the same data. IE there&#39;s no magical thread protection baked into S7 that I don&#39;t know about....</div><div><br></div><div>I&#39;m wrestling with how to deal with this correctly. One option is to allow users to designate an s4m instance as always-high or always-low, basically saying if you need to mix low and high priority you should treat it like an actor model and have two interpreters  that message each other and share data through some non-scheme shared data structure (like max buffers or tables). This might be ok because there is a way for me to insure incoming max messages from any thread are either promoted or demoted. </div><div><br></div><div>I suppose another option is to get into critical sections, but I can&#39;t see how that make sense if we don&#39;t want low priority actions to have the chance of locking out high ones. </div><div><br></div><div>Strangely, I have not had any issues yet. But I presume that just means I&#39;ve been lucky. Cycling 74 does not (anymore) allow the javascript object to work in both threads, and I&#39;m thinking it must have been around thread stability issues.</div><div><br></div><div>Any thoughts most welcome!</div><div>iain</div></div>
</blockquote></div>
_______________________________________________<br>
Cmdist mailing list<br>
<a href="mailto:Cmdist@ccrma.stanford.edu" target="_blank">Cmdist@ccrma.stanford.edu</a><br>
<a href="https://cm-mail.stanford.edu/mailman/listinfo/cmdist" rel="noreferrer" target="_blank">https://cm-mail.stanford.edu/mailman/listinfo/cmdist</a><br>
</blockquote></div>