<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://www.eiffelroom.org" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>eiffelroom - Using externals in multithreaded applications - Comments</title>
 <link>http://www.eiffelroom.org/article/using_externals_in_multithreaded_applications</link>
 <description>Comments for &quot;Using externals in multithreaded applications&quot;</description>
 <language>en</language>
<item>
 <title>Using externals in multithreaded applications</title>
 <link>http://www.eiffelroom.org/article/using_externals_in_multithreaded_applications</link>
 <description>&lt;p&gt;Using a C/C++ external in an Eiffel system is pretty easy. Simply do a C/C++ inline and provide the arguments to the C/C++ externals.&lt;/p&gt;

&lt;p&gt;When transforming the same system into a multithreaded application one has to pay attention to something else: C/C++ externals that may take a long time to execute.&lt;/p&gt;


&lt;h2 id=&quot;toc0&quot;&gt;Using blocking qualifier&lt;/h2&gt;
 The issue is specific to the Eiffel Software GC implementation which is a &lt;strong&gt;stop the world&lt;/strong&gt; type of GC. In other words, when a GC cycle is triggered, all the running threads have to be stopped. However, when a thread is executing an external C/C++ code, the Eiffel runtime has no way to stop that thread reliably on all the supported platforms. Consequence, the GC cycle will start only after the external C/C++ code has completed and this could cause an unacceptable delay.&lt;p&gt;The adopted solution was to add a new qualifier to C/C++ externals: &lt;strong&gt;blocking&lt;/strong&gt;. This keywords directly follows to the C or C++ keyword in the external specification. Here is an example taken from the &lt;a class=&quot;&quot; style=&quot;&quot; href=&quot;/locate/EiffelBase&quot;&gt;EiffelBase&lt;/a&gt; library &lt;code class=&quot;geshifilter eiffel&quot;&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=site%3Ahttp%3A%2F%2Fdocs.eiffel.com%2Feiffelstudio%2Flibraries+EXECUTION_ENVIRONMENT&amp;btnI=I%27m+Feeling+Lucky&quot;&gt;&lt;span style=&quot;color: #800000&quot;&gt;EXECUTION_ENVIRONMENT&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;#125;&lt;/span&gt;.&lt;span style=&quot;color: #000060;&quot;&gt;sleep&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;geshifilter eiffel&quot; style=&quot;font-family: monospace;&quot;&gt;sleep &lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;#40;&lt;/span&gt;nanoseconds: INTEGER_64&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #0600FF; font-weight: bold;&quot;&gt;is&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008000; font-style: italic;&quot;&gt;-- Suspend thread execution for interval specified in&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008000; font-style: italic;&quot;&gt;-- `nanoseconds&#039; (1 nanosecond = 10^(-9) second).&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF; font-weight: bold;&quot;&gt;require&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; non_negative_nanoseconds: nanoseconds &amp;gt;= &lt;span style=&quot;color: #FF0000;&quot;&gt;0&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF; font-weight: bold;&quot;&gt;external&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0080A0;&quot;&gt;&amp;quot;C blocking use &lt;span style=&quot;color: #005070; font-weight: bold;&quot;&gt;%&amp;quot;&lt;/span&gt;eif_threads.h&lt;span style=&quot;color: #005070; font-weight: bold;&quot;&gt;%&amp;quot;&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF; font-weight: bold;&quot;&gt;alias&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0080A0;&quot;&gt;&amp;quot;eif_thr_sleep&amp;quot;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF; font-weight: bold;&quot;&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Since it is cumbersome to have to go through all the externals and add the missing &lt;strong&gt;blocking&lt;/strong&gt; qualifier, one may ask, why it isn&#039;t the default behavior. There are 2 elements of response: &lt;ol&gt;
    &lt;li&gt;C/C++ externals that last a long time are usually rare.&lt;/li&gt;
    &lt;li&gt;Making a C/C++ externals blocking by default would potentially cause race conditions (thus random results/crashes) when the C/C++ externals call back to Eiffel code.&lt;/li&gt;
&lt;/ol&gt;

&lt;/p&gt;

&lt;p&gt;This is really point #2 that made us choose the current described solution of adding the &lt;strong&gt;blocking&lt;/strong&gt; qualifier wherever it was needed, since when you have to choose between a deadlock and a crash, the deadlock alternative is much easier to debug.&lt;/p&gt;

&lt;p&gt;To figure out when you need to put a blocking qualifier, simply execute your program and when it seems to freeze, look at the call stacks for the various threads in a C debugger. Usually, the scenario is the following: &lt;ol&gt;
    &lt;li&gt;One thread is taking all the CPU by looping&lt;/li&gt;
    &lt;li&gt;All the other threads are blocked in some thread synchronization routines&lt;/li&gt;
    &lt;li&gt;One thread is executing a C external call.&lt;/li&gt;
&lt;/ol&gt;

&lt;/p&gt;

&lt;p&gt;That&#039;s it, #3 is the place where you need to add the blocking qualifier.&lt;/p&gt;


&lt;h2 id=&quot;toc1&quot;&gt;Callbacks from C to Eiffel&lt;/h2&gt;
&lt;p&gt;Let&#039;s tackle a more complicated scenario where you have a C/C++ external calling some Eiffel code. Here is what you need to do. First, the C/C++ externals needs to be marked blocking, then in the C/C++ code where you do a call back to the Eiffel code, you need to prefix and suffix the call by the following macros &lt;code class=&quot;geshifilter c&quot;&gt;EIF_ENTER_EIFFEL&lt;/code&gt; and &lt;code class=&quot;geshifilter c&quot;&gt;EIF_EXIT_EIFFEL&lt;/code&gt;. The reason is that when executing the C code for a blocking C external, it is as if the runtime forgot about the existence of that thread. Calling &lt;code class=&quot;geshifilter c&quot;&gt;EIF_ENTER_EIFFEL&lt;/code&gt; simply tells the runtime that the thread is again live. Calling &lt;code class=&quot;geshifilter c&quot;&gt;EIF_EXIT_EIFFEL&lt;/code&gt; has the effect of making the runtime to forget the existence of that thread.&lt;/p&gt;

&lt;p&gt;Moreover before calling the Eiffel routine, you need to ensure that no GC cycle is happening, as it is possible that while you were calling &lt;code class=&quot;geshifilter c&quot;&gt;EIF_ENTER_EIFFEL&lt;/code&gt; the runtime was performing a GC cycle and  you do not want to execute some Eiffel code while the GC is in a cycle. To wait for the completion of any pending GC cycle, one has to use the &lt;code class=&quot;geshifilter c&quot;&gt;RTGC&lt;/code&gt; macro.&lt;/p&gt;

&lt;p&gt;For example, here is what one would typically have:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;geshifilter eiffel&quot; style=&quot;font-family: monospace;&quot;&gt;my_c_routine &lt;span style=&quot;color: #0600FF; font-weight: bold;&quot;&gt;is&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF; font-weight: bold;&quot;&gt;external&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0080A0;&quot;&gt;&amp;quot;C blocking use &lt;span style=&quot;color: #005070; font-weight: bold;&quot;&gt;%&amp;quot;&lt;/span&gt;some_header_file.h&lt;span style=&quot;color: #005070; font-weight: bold;&quot;&gt;%&amp;quot;&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF; font-weight: bold;&quot;&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;geshifilter c&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;span style=&quot;color: #993333;&quot;&gt;void&lt;/span&gt; my_c_routine &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #993333;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;/* Some C code here. */&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; EIF_ENTER_EIFFEL;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; RTGC;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; your_eiffel_routine_call &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;eif_access&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;my_object&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;, ....&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; EIF_EXIT_EIFFEL;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;/* Some other C code here. */&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;


&lt;h2 id=&quot;toc2&quot;&gt;External threads callbacks&lt;/h2&gt;
 If your callback is performed in a thread which was not created by the Eiffel runtime through the &lt;a class=&quot;&quot; style=&quot;&quot; href=&quot;/locate/EiffelThread&quot;&gt;EiffelThread&lt;/a&gt; library, then some more code has to be added.&lt;p&gt;The first time your external code wants to call some Eiffel code, you need to initialize the runtime for that particular thread of execution by calling the &lt;code class=&quot;geshifilter c&quot;&gt;EIF_INITIALIZE_AUX_THREAD&lt;/code&gt; macro.&lt;/p&gt;

&lt;p&gt;Once it is initialized, you can perform the call back in the same manner as in the second part of the article.&lt;/p&gt;

&lt;p&gt;After the completion of the call, you have 2 possibilities: &lt;ul&gt;
    &lt;li&gt; Clear the data register for the current thread (meaning you know that this thread is never to execute Eiffel code again)&lt;/li&gt;
    &lt;li&gt; Wait for a notification that the current thread is going to terminate.&lt;/li&gt;
&lt;/ul&gt;

&lt;/p&gt;

&lt;p&gt;In both cases, you need to manually call &lt;code class=&quot;geshifilter c&quot;&gt;eif_thr_exit&lt;/code&gt; to free the Eiffel runtime allocated memory for that thread.&lt;/p&gt;

&lt;p&gt;To summarize your C callback routine could look like:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;geshifilter c&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;span style=&quot;color: #993333;&quot;&gt;void&lt;/span&gt; my_c_routine &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #993333;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; EIF_INITIALIZE_AUX_THREAD;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; EIF_ENTER_EIFFEL;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; RTGC;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; your_eiffel_routine_call &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;eif_access&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;my_object&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;, ....&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; EIF_EXIT_EIFFEL;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; eif_thr_exit&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;I hope this tutorial was helpful.&lt;/p&gt;

</description>
 <comments>http://www.eiffelroom.org/article/using_externals_in_multithreaded_applications#comments</comments>
 <category domain="http://www.eiffelroom.org/taxonomy/term/3">Tutorial</category>
 <category domain="http://www.eiffelroom.org/taxonomy/term/9">Advanced</category>
 <category domain="http://www.eiffelroom.org/tag/eiffelstudio">EiffelStudio</category>
 <category domain="http://www.eiffelroom.org/tag/eiffelthread">eiffelthread</category>
 <category domain="http://www.eiffelroom.org/tag/gc">gc</category>
 <category domain="http://www.eiffelroom.org/tag/thread">thread</category>
 <pubDate>Mon, 07 Jan 2008 13:39:51 -0800</pubDate>
 <dc:creator>manus_eiffel</dc:creator>
 <guid isPermaLink="false">249 at http://www.eiffelroom.org</guid>
</item>
</channel>
</rss>
