<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="/assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Jason Madden (Posts about threads)</title><link>https://seecoresoftware.com/</link><description></description><atom:link href="https://seecoresoftware.com/blog/categories/threads.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2021 &lt;a href="mailto:jason@seecoresoftware.com"&gt;Jason Madden&lt;/a&gt; </copyright><lastBuildDate>Sat, 04 Dec 2021 18:43:34 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>GNU Pth: gevent for C</title><link>https://seecoresoftware.com/blog/2018/06/gnu-pth-gevent-for-c.html</link><dc:creator>Jason Madden</dc:creator><description>&lt;div&gt;&lt;p&gt;The &lt;a class="reference external" href="https://www.gnu.org/software/pth/"&gt;GNU Pth&lt;/a&gt; (&lt;em&gt;p&lt;/em&gt;ortable &lt;em&gt;th&lt;/em&gt;reads) library is a "very portable
POSIX/ANSI-C library for Unix platforms which
provides...non-preemptive multithreading inside event-driven
applications." Sound familiar? It's &lt;a class="reference external" href="https://seecoresoftware.com/blog/categories/cat_gevent.html"&gt;gevent&lt;/a&gt;
for C!&lt;/p&gt;
&lt;!-- TEASER_END --&gt;
&lt;p&gt;I'd vaguely heard about GNU Pth before, but only as a "user-level
threading library." I had no idea it was non-preemptive. I assumed it
was something like the old &lt;a class="reference external" href="https://en.wikipedia.org/wiki/LinuxThreads"&gt;LinuxThreads&lt;/a&gt; library, which used
multi-processing and virtual memory tricks to simulate multiple threads.&lt;/p&gt;
&lt;p&gt;How wrong I was! &lt;a class="reference external" href="http://nullprogram.com/blog/2010/12/21/"&gt;This article&lt;/a&gt; on making &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Ncurses"&gt;ncurses&lt;/a&gt; (a terminal user
interface library—a GUI for the console) cooperate with GNU Pth
got me to take a closer look at GNU Pth and its implementation. You
can read all about it in that article and the &lt;a class="reference external" href="https://www.gnu.org/software/pth/pth-manual.html"&gt;manual&lt;/a&gt;; here I'll hit
some highlights.&lt;/p&gt;
&lt;div class="section" id="greenlets"&gt;
&lt;h2&gt;greenlets&lt;/h2&gt;
&lt;p&gt;To implement the concept of multiple threads of control in a
single-threaded process, instead of greenlets, Pth uses the C standard
&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Setjmp.h"&gt;setjmp/longjmp&lt;/a&gt; functions (or enhanced equivalents). These basically
let a program save its call stack, swap it out, and return to it
later, which is the key requirement for a greenlet.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="monkey-patching"&gt;
&lt;h2&gt;monkey-patching&lt;/h2&gt;
&lt;p&gt;Pth provides a cooperative API that programs can call, but it also
provides monkey-patching so existing programs can be made to be
cooperative. The "soft" version of this monkey-patching is done at
compile time, redirecting standard functions to Pth's cooperative
versions:&lt;/p&gt;
&lt;pre class="code C"&gt;&lt;a name="rest_code_d0297deeddb2413495020c8d2659531b-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define fork          pth_fork&lt;/span&gt;
&lt;a name="rest_code_d0297deeddb2413495020c8d2659531b-2"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define waitpid       pth_waitpid&lt;/span&gt;
&lt;a name="rest_code_d0297deeddb2413495020c8d2659531b-3"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define system        pth_system&lt;/span&gt;
&lt;a name="rest_code_d0297deeddb2413495020c8d2659531b-4"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define nanosleep     pth_nanosleep&lt;/span&gt;
&lt;a name="rest_code_d0297deeddb2413495020c8d2659531b-5"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define usleep        pth_usleep&lt;/span&gt;
&lt;a name="rest_code_d0297deeddb2413495020c8d2659531b-6"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define sleep         pth_sleep&lt;/span&gt;
&lt;a name="rest_code_d0297deeddb2413495020c8d2659531b-7"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define sigprocmask   pth_sigmask&lt;/span&gt;
&lt;a name="rest_code_d0297deeddb2413495020c8d2659531b-8"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define sigwait       pth_sigwait&lt;/span&gt;
&lt;a name="rest_code_d0297deeddb2413495020c8d2659531b-9"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define select        pth_select&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;There's an additional "hard" version that catches the actual system
calls themselves and provides link-able function definitions under the
original names. This is more similar to what gevent does.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="event-primitives-are-exposed"&gt;
&lt;h2&gt;event primitives are exposed&lt;/h2&gt;
&lt;p&gt;Much like with &lt;a class="reference external" href="https://seecoresoftware.com/blog/2018/05/gevent-hub.html"&gt;gevent's hub and loop&lt;/a&gt;, the
Pth event loop primitives are exposed to the user. In this way, the
article could monkey-patch the ncurses event loop's blocking function
and replace it with one that was Pth cooperative.&lt;/p&gt;
&lt;pre class="code C"&gt;&lt;a name="rest_code_cea75a6bf439470f9f759b5f80fcd43d-1"&gt;&lt;/a&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;pth_getch&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
&lt;a name="rest_code_cea75a6bf439470f9f759b5f80fcd43d-2"&gt;&lt;/a&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_cea75a6bf439470f9f759b5f80fcd43d-3"&gt;&lt;/a&gt;    &lt;span class="n"&gt;pth_event_t&lt;/span&gt; &lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_cea75a6bf439470f9f759b5f80fcd43d-4"&gt;&lt;/a&gt;    &lt;span class="n"&gt;ev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pth_event&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PTH_EVENT_FD&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PTH_UNTIL_FD_READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_cea75a6bf439470f9f759b5f80fcd43d-5"&gt;&lt;/a&gt;    &lt;span class="n"&gt;pth_wait&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_cea75a6bf439470f9f759b5f80fcd43d-6"&gt;&lt;/a&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;getch&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
&lt;a name="rest_code_cea75a6bf439470f9f759b5f80fcd43d-7"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_cea75a6bf439470f9f759b5f80fcd43d-8"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#undef getch&lt;/span&gt;
&lt;a name="rest_code_cea75a6bf439470f9f759b5f80fcd43d-9"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define getch pth_getch&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description><category>C</category><category>gevent</category><category>GNU</category><category>portable</category><category>python</category><category>threads</category><guid>https://seecoresoftware.com/blog/2018/06/gnu-pth-gevent-for-c.html</guid><pubDate>Mon, 18 Jun 2018 15:15:07 GMT</pubDate></item></channel></rss>