{"id":1966,"date":"2023-12-06T12:22:29","date_gmt":"2023-12-06T11:22:29","guid":{"rendered":"https:\/\/oopm.org\/?page_id=1966"},"modified":"2024-12-13T11:32:52","modified_gmt":"2024-12-13T10:32:52","slug":"52-preemptive-coroutines","status":"publish","type":"page","link":"https:\/\/oopm.org\/?page_id=1966","title":{"rendered":"16.2 Preemptive coroutines"},"content":{"rendered":"<div class=\"pdfprnt-buttons pdfprnt-buttons-page pdfprnt-top-right\"><a href=\"https:\/\/oopm.org\/index.php?rest_route=wpv2pages1966&print=pdf\" class=\"pdfprnt-button pdfprnt-button-pdf\" target=\"_blank\"><img decoding=\"async\" src=\"https:\/\/oopm.org\/wp-content\/plugins\/pdf-print\/images\/pdf.png\" alt=\"image_pdf\" title=\"View PDF\" \/><\/a><a href=\"https:\/\/oopm.org\/index.php?rest_route=wpv2pages1966&print=print\" class=\"pdfprnt-button pdfprnt-button-print\" target=\"_blank\"><img decoding=\"async\" src=\"https:\/\/oopm.org\/wp-content\/plugins\/pdf-print\/images\/print.png\" alt=\"image_print\" title=\"Print Content\" \/><\/a><\/div>\n<p class=\"wp-block-paragraph\">In this section, we describe <em>Preemptive coroutines, <\/em>which<strong><em> <\/em><\/strong>may be used to implement parallel objects and scheduling of parallel objects.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So far coroutines have been cooperative in the sense that a coroutine executes until it voluntarily suspends execution. Using cooperative coroutines, at most one coroutine executes at a given time during program execution. Synchronization between coroutines may thus not be needed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A preemptive coroutine may be suspended by an&nbsp;external signal at any time during its execution. That is, a preemptive coroutine does not control when it has to give up control. As we shall see later, this makes it possible to implement <em>time-sharing<\/em> between two or more pre-emptive coroutines.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Time-sharing is a standard computing term that describes the situation where two or more parallel objects share the same computing resource (CPU or core). This enables multi-tasking, which is the concurrent execution of multiple tasks (processes) over a certain period of time. In the simple form where only one CPU\/core is available, at most one coroutine executes at a given time, but since it may be suspended (the term <em>interrupted<\/em> is the general computing term here ) at an arbitrary point during execution, it simulates the effect of the coroutines executing in true parallel by executing segments of the code in an <em>interleaved<\/em> manner. The time slots allocated to a coroutine is typically in the order of milliseconds, and this implies that it is necessary to synchronize access to common data objects.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A cooperative coroutine may be resumed using a <code>call<\/code>-method. For a preemptive coroutine, an <code>attach<\/code>-method is used:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>s: <strong>obj<\/strong> \n   ...\n   s.suspend\n   ...\n...\ns.attach(100)\n...<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>s<\/code> is executing a sequence of statements. We assume that <code>s<\/code> during its instantiation executes a suspend and return to its invoker. Otherwise it does not makes sense to resume <code>s<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The statement <code>s.attach(100)<\/code> implies that <code>s<\/code> is resumed. The argument 100 to <code>attach<\/code> implies that <code>s<\/code> is preemptively suspended after 100 units of execution. The unit depends on the actual implementation of qBeta. For here we assume that the unit is a micro second.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We next sketch an example using preemptive coroutines in the domain of file-processing. The object <code>smallSys<\/code> has three preemptive coroutines <code>reader<\/code>, <code>processor<\/code> and <code>writer<\/code>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>reader<\/code> reads the next integer from <code>inFile<\/code>; the <code>processor<\/code> computes a function from this value; the result of this is written by the <code>writer<\/code> to the file <code>outFile<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The three coroutines communicate values through the <code>buffer<\/code>-objects <code>inBuffer<\/code> and <code>outBuffer<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>smallSys: <strong>obj<\/strong>\n   inFile,outFile: <strong>obj<\/strong> File\n   inBuffer, outBuffer: <strong>obj<\/strong>\n      add(V: <strong>var<\/strong> inter): ...\n      get -&gt; V: <strong>var<\/strong> integer: ...\n      ...\n   reader: <strong>obj<\/strong>\n      reader.suspend\n      cycle\n         inBuffer.add(inFile.read)\n   processor: <strong>obj<\/strong>  \n      compute: ...    \n      processor.suspend\n      cycle\n         outBuffer.add(compute(inBuffer.get))\n   writer: <strong>obj<\/strong>\n      writer.suspend\n      cycle\n         outFile.write(nextValue)\n   done -&gt; B: <strong>var<\/strong> Boolean: ...\n-- open inFile and outFile\nloop:\n   cycle\n      reader.attach(10)\n      processor.attach(100)\n      writer.attach(10)\n      if (done) :then\n         leave(loop)\n-- close inFile and outFile <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The three coroutines start by executing a suspend; the <code>reader<\/code> then repeatedly reads a value from <code>inFile<\/code> and adds it to the <code>inBuffer<\/code>; the processor repeatedly gets a value from the <code>inBuffer<\/code>, compute a new value, which is added to the <code>outBuffer<\/code>; the <code>writer<\/code> repeatedly reads a value from the <code>outBuffer<\/code> and writes it to the <code>outFile<\/code>. <code>Compute<\/code> is left unspecified.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>smallSys<\/code> object starts by opening the files; it then repeatedly resumes the three coroutines; the <code>reader<\/code> and <code>writer<\/code> get slots of 10 milliseconds; the <code>processor<\/code> gets a slot of 100 milliseconds. This goes on until the <code>done<\/code>-method returns true &#8211; <code>done<\/code> is unspecified.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note here, that <code>smallSys<\/code> is in full control of how to schedule the coroutines and the size of the timeslots given to each of them. This is a feature that is rarely supported by most mainstream object-oriented languages. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The buffers <code>inBuffer<\/code> and <code>outBuffer<\/code> are shared objects and synchronisation is needed, but left unspecified here.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Although the example is sketchy, it does resemble an example that may arise in practice. <\/p>\n<div style=\"display:flex; gap:10px;justify-content:center\" class=\"wps-pgfw-pdf-generate-icon__wrapper-frontend\">\n\t\t<a  href=\"https:\/\/oopm.org?action=genpdf&amp;id=1966\" class=\"pgfw-single-pdf-download-button\" ><img src=\"https:\/\/oopm.org\/wp-content\/plugins\/pdf-generator-for-wp\/admin\/src\/images\/PDF_Tray.svg\" title=\"Generate PDF\" style=\"width:auto; height:45px;\"><\/a>\n\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>In this section, we describe Preemptive coroutines, which may be used to implement parallel objects and scheduling of parallel objects. So far coroutines have been cooperative in the sense that a coroutine executes until it voluntarily suspends execution. Using cooperative coroutines, at most one coroutine executes at a given time during program execution. Synchronization between [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1972,"menu_order":2,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1966","page","type-page","status-publish","hentry"],"mb":[],"mfb_rest_fields":["title","gutenberg_elementor_mode"],"_links":{"self":[{"href":"https:\/\/oopm.org\/index.php?rest_route=\/wp\/v2\/pages\/1966","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/oopm.org\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/oopm.org\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/oopm.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/oopm.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1966"}],"version-history":[{"count":43,"href":"https:\/\/oopm.org\/index.php?rest_route=\/wp\/v2\/pages\/1966\/revisions"}],"predecessor-version":[{"id":10326,"href":"https:\/\/oopm.org\/index.php?rest_route=\/wp\/v2\/pages\/1966\/revisions\/10326"}],"up":[{"embeddable":true,"href":"https:\/\/oopm.org\/index.php?rest_route=\/wp\/v2\/pages\/1972"}],"wp:attachment":[{"href":"https:\/\/oopm.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1966"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}