blob: 0fb4f25c27db4cf080c9bfa5fc6dafa9d24376ab [file] [log] [blame] [raw]
<!DOCTYPE html><html><head><meta charset="utf-8" /><meta content="IE=edge" http-equiv="X-UA-Compatible" /><meta content="width=device-width, initial-scale=1, maximum-scale=2.0, user-scalable=yes, minimal-ui=yes" name="viewport" /><title>facil.io - lib evio, kqueue/epoll abstraction in C.</title><meta content="facil.io - lib evio, kqueue/epoll abstraction in C." name="description" /><link href="https://fonts.googleapis.com/css?family=Montserrat|Quicksand|Karla" rel="stylesheet" type="text/css" /><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script><link href="/assets/styles/main.css" rel="stylesheet" type="text/css" /><script type="application/ld+json">{"@context":"http://schema.org","@type":"WebSite","url":"http://facil.io","name":"facil.io","description":"facil.io - a light web application framework in C, with support for HTTP, WebSockets and Pub/Sub out of the box.","keywords":"C, web, framework, websockets, websocket, realtime, real-time, easy","image":"http://facil.io/website/logo/facil-io.svg","author":[{"@type":"Person","name":"Bo (Myst)","url":"http://stackoverflow.com/users/4025095/myst","email":"bo(at)facil.io"}],"sourceOrganization":{"@context":"http://schema.org","@type":"Organization","name":"Plezi","url":"http://facil.io","description":"facil.io - a light web application framework in C, with support for HTTP, WebSockets and Pub/Sub out of the box.","logo":"http://facil.io/website/logo/facil-io.svg","image":"http://facil.io/website/logo/facil-io.svg","email":"bo(at)facil.io","member":[{"@type":"Person","name":"Bo (Myst)","url":"http://stackoverflow.com/users/4025095/myst","email":"bo(at)facil.io"}]}}</script><meta content="facil.io" name="apple-mobile-web-app-title" /><meta content="facil.io - the C Web Application Framework" name="application-name" /><meta content="#b91d47" name="msapplication-TileColor" /><meta content="/mstile-144x144.png" name="msapplication-TileImage" /><meta content="#ffffff" name="theme-color" /></head><body><a href="/" id="logo"></a><input id="show_nav" type="checkbox" /><nav id="top_nav"><ul><li><a href="/0.7.x/index">Latest Docs</a></li><li><a href="https://github.com/boazsegev/facil.io" target="_blank">Source Code</a></li><li><a href="javascript: change_themes();" id="theme">Night Theme</a></li></ul></nav><input id="show_sidebar" type="checkbox" /><nav id="side_bar"><h2 id="version-0-6-x"><a href="/0.6.x/index">Version 0.6.x</a></h2>
<ul>
<li><a href="/0.6.x/api">API Overview</a></li>
<li><a href="/0.6.x/modules">The Modules</a></li>
</ul>
<h3 id="core-api"><a href="/0.6.x/facil">Core API</a></h3>
<ul>
<li><a href="/0.6.x/defer">Event scheduling</a></li>
<li><a href="/0.6.x/evio">Low Level Polling</a></li>
<li><a href="/0.6.x/sock">Low Level Sockets</a></li>
<li><a href="/0.6.x/fio_mem">Memory Allocation</a></li>
</ul>
<h3 id="extensions">Extensions</h3>
<ul>
<li><a href="/0.6.x/http">HTTP</a></li>
<li><a href="/0.6.x/websockets">WebSockets</a></li>
<li><a href="/0.6.x/pubsub">Pub/Sub</a></li>
<li><a href="/0.6.x/fio_cli">CLI (command line)</a></li>
</ul>
<h3 id="the-fiobj-types"><a href="/0.6.x/fiobj">The FIOBJ types</a></h3>
<ul>
<li><a href="/0.6.x/fiobj_primitives">Primitives</a></li>
<li><a href="/0.6.x/fiobj_numbers">Numbers</a></li>
<li><a href="/0.6.x/fiobj_str">Strings</a></li>
<li><a href="/0.6.x/fiobj_ary">Array</a></li>
<li><a href="/0.6.x/fiobj_hash">HashMap</a></li>
<li><a href="/0.6.x/fiobj_json">JSON</a></li>
</ul>
<h3 id="core-types"><a href="/0.6.x/types">Core Types</a></h3>
<ul>
<li><a href="/0.6.x/fio_ary">C Arrays</a></li>
<li><a href="/0.6.x/fio_hashmap">C HashMap</a></li>
<li><a href="/0.6.x/fio_llist">Linked Lists</a></li>
</ul>
</nav><div id="md_container"><div class='toc'><ul>
<li>
<a href="#the-evented-io-library-kqueue-epoll-abstraction">The Evented IO Library - KQueue/EPoll abstraction</a>
<ul>
<li>
<a href="#event-callbacks">Event Callbacks</a>
</li>
<li>
<a href="#the-evio-api">The <code>evio</code> API</a>
<ul>
<li>
<a href="#evio_create"><code>evio_create</code></a>
</li>
<li>
<a href="#evio_review"><code>evio_review</code></a>
</li>
<li>
<a href="#evio_close"><code>evio_close</code></a>
</li>
<li>
<a href="#evio_isactive"><code>evio_isactive</code></a>
</li>
<li>
<a href="#evio_add"><code>evio_add</code></a>
</li>
<li>
<a href="#evio_open_timer"><code>evio_open_timer</code></a>
</li>
<li>
<a href="#evio_set_timer"><code>evio_set_timer</code></a>
</li>
</ul>
</li>
<li>
<a href="#known-issues">Known Issues</a>
</li>
</ul>
</li>
</ul>
</div><h1 id="the-evented-io-library-kqueue-epoll-abstraction">The Evented IO Library - KQueue/EPoll abstraction</h1>
<p>The <code>evio.h</code> library, is a KQueue/EPoll abstraction for edge triggered events and is part of <a href="./facil.md"><code>facil.io</code>&#39;s</a> core.</p>
<p>It should be noted that exactly like <code>epoll</code> and <code>kqueue</code>, <code>evio.h</code> might produce unexpected results if forked after initialized, since this will cause the <code>epoll</code>/<code>kqueue</code> data to be shared across processes, even though these processes will not have access to new file descriptors (i.e. <code>fd</code> 90 on one process might reference file &quot;A&quot; while on a different process the same <code>fd</code> (90) might reference file &quot;B&quot;).</p>
<p>This documentation isn&#39;t relevant for <code>facil.io</code> users. <code>facil.io</code> implements <code>evio.h</code> callbacks and <code>evio.h</code> cannot be used without removing <code>facil.h</code> and <code>facil.c</code> from the project.</p>
<p>This file is here as quick reference to anyone interested in maintaining <code>facil.io</code> or learning about how it&#39;s insides work.</p>
<h2 id="event-callbacks">Event Callbacks</h2>
<p>Event callbacks are defined during the linking stage and are hardwired once compilation is complete.</p>
<p><code>void evio_on_data(void *)</code> - called when the file descriptor has incoming data. This is <strong>one-shot</strong> triggered, meaning it will <strong>not</strong> be called again unless the <code>evio_add</code> (or <code>evio_set_timer</code>) are called.</p>
<p><code>void evio_on_ready(void *)</code> - called when the file descriptor is ready to send data (outgoing).</p>
<p><code>void evio_on_error(void *)</code> - called when a file descriptor raises an error while being polled.</p>
<p><code>void evio_on_close(void *)</code> - called when a file descriptor was closed REMOTELY. <code>evio_on_close</code> will NOT get called when a connection is closed locally, unless using <code>sock.h</code>&#39;s callback, the <code>sock_on_close</code> function.</p>
<p><strong>Notice</strong>: Both EPoll and KQueue will <strong>not</strong> raise an event for an <code>fd</code> that was closed using the native <code>close</code> function, so unless using <code>sock.h</code> or calling <code>evio_on_close</code>, the <code>evio_on_close</code> callback will only be called for remote events.</p>
<p><strong>Notice</strong>: The <code>on_open</code> event is missing by design, as it is expected that any initialization required for the <code>on_open</code> event will be performed before attaching the file descriptor (socket/timer/pipe) to <code>evio</code> using <a href=""><code>evio_add</code></a>.</p>
<h2 id="the-evio-api">The <code>evio</code> API</h2>
<h3 id="evio_create"><code>evio_create</code></h3>
<pre><code class='highlight'><span class="kt">intptr_t</span> <span class="n">evio_create</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</code></pre>
<p>Creates the <code>epoll</code> or <code>kqueue</code> object.</p>
<p>It&#39;s impossible to add or remove file descriptors from the polling system before
calling this method.</p>
<p>Returns -1 on error, otherwise returns a unique value representing the <code>epoll</code>
or <code>kqueue</code> object. The returned value can be safely ignored.</p>
<p><strong>NOTE</strong>: Once an <code>epoll</code> / <code>kqueue</code> object was opened, <code>fork</code> should be avoided,
since ALL the events will be shared among the forked processes (while not ALL
the file descriptors are expected to be shared).</p>
<h3 id="evio_review"><code>evio_review</code></h3>
<pre><code class='highlight'><span class="kt">int</span> <span class="n">evio_review</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span> <span class="n">timeout_millisec</span><span class="p">)</span>
</code></pre>
<p>Reviews any pending events (up to <code>EVIO_MAX_EVENTS</code>) and calls any callbacks.</p>
<p>Waits up to <code>timeout_millisec</code> for events to occur.</p>
<p>Returns -1 on error, otherwise returns the number of events handled.</p>
<h3 id="evio_close"><code>evio_close</code></h3>
<pre><code class='highlight'><span class="kt">void</span> <span class="n">evio_close</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</code></pre>
<p>Closes the <code>epoll</code> / <code>kqueue</code> object, releasing it&#39;s resources (important if
forking!).</p>
<h3 id="evio_isactive"><code>evio_isactive</code></h3>
<pre><code class='highlight'><span class="kt">int</span> <span class="n">evio_isactive</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</code></pre>
<p>Returns true if the evio is available for adding or removing file descriptors.</p>
<h3 id="evio_add"><code>evio_add</code></h3>
<pre><code class='highlight'><span class="kt">int</span> <span class="n">evio_add</span><span class="p">(</span><span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">callback_arg</span><span class="p">)</span>
</code></pre>
<p>Adds a file descriptor to the polling object (ONE SHOT).</p>
<p>Returns -1 on error, otherwise return value is system dependent and can be
safely ignored.</p>
<h3 id="evio_open_timer"><code>evio_open_timer</code></h3>
<pre><code class='highlight'><span class="kt">intptr_t</span> <span class="n">evio_open_timer</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</code></pre>
<p>Creates a timer file descriptor, system dependent.</p>
<p>Returns -1 on error, or a valid fd on success.</p>
<p>NOTE: Systems have a limit on the number of timers that can be opened.</p>
<h3 id="evio_set_timer"><code>evio_set_timer</code></h3>
<pre><code class='highlight'><span class="kt">intptr_t</span> <span class="n">evio_set_timer</span><span class="p">(</span><span class="kt">int</span> <span class="n">fd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">callback_arg</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">milliseconds</span><span class="p">)</span>
</code></pre>
<p>Adds a timer file descriptor, so that callbacks will be called for it&#39;s events.</p>
<p>Returns -1 on error, otherwise return value is system dependent.</p>
<h2 id="known-issues">Known Issues</h2>
<ul>
<li><p>On Linux, using <code>epoll</code>, the <code>EPOLLONESHOT</code> flag doesn&#39;t remove the <code>fd</code> from <code>epoll</code> descriptor, requiring <code>EPOLL_CTL_MOD</code> instead of <code>EPOLL_CTL_ADD</code>.</p>
<p>To support a stateless API, where the user doesn&#39;t need to remember if a specific <code>fd</code> was previously passed to the <code>evio_add</code> function, the <code>epoll</code> implementation performs two system calls for new connections instead of a single system call (<code>EPOLL_CTL_ADD</code> is performed only if <code>EPOLL_CTL_MOD</code> fails).</p></li>
</ul>
</div><a href="/" id="sign"></a><div class="hidden" id="notice"><a class="notice_close" onclick="hide_notice()">X</a><div id="notice_text"></div></div><script>function change_themes() {
if(localStorage.getItem("theme") == 'dark') {
localStorage.setItem("theme", "light");
} else {
localStorage.setItem("theme", "dark");
}
$('body')[0].className = localStorage.getItem("theme");
set_theme_link();
$('#show_nav').attr('checked', false);
return false;
};
function sidebar_name() { return window.location.pathname.slice(0, window.location.pathname.lastIndexOf("/")); }
function on_sidebar_link(e) {
sessionStorage.setItem("sidebar.expect", sidebar_name());
sessionStorage.setItem("sidebar.pos", document.getElementById("side_bar").scrollTop);
}
function load_sidebar_pos() {
var e = document.getElementById("side_bar");
if(!e) {
console.warn("No sidebar detected");
return;
}
var expect = sidebar_name();
if(sessionStorage.getItem("sidebar.expect") == expect) {
e.scrollTo(0, parseInt(sessionStorage.getItem("sidebar.pos")));
} else {
sessionStorage.setItem("sidebar.expect", false);
sessionStorage.setItem("sidebar.pos", 0);
}
if(e) {
// add link callbacks
var links = document.links;
var count = links.length;
for (var i = 0; i < count; i++) {
var href = links[i].href;
if(href.startsWith(document.location.origin)) {
href = href.slice(document.location.origin.length);
}
if(href.startsWith(expect)) {
/* add link event */
links[i].addEventListener("click", on_sidebar_link);
}
}
}
};
load_sidebar_pos();
function set_theme_link() {
$("#theme").html( ( (localStorage.getItem("theme") == 'dark') ? "Day" : "Night") + " Theme" );
}
$('body')[0].className = (localStorage.getItem("theme") == 'dark') ? "dark" : "light";
set_theme_link();
function show_notice() { document.getElementById("notice").classList.remove('hidden'); };
function hide_notice() { document.getElementById("notice").classList.add('hidden'); };
$('#toc').on("touchstart", function (e) { return true; } );
$('#toc').on("hover", function (e) { return true; } );
// hljs.initHighlighting();
// Google Analytics
// if(location.hostname != "localhost") {
// (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
// (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
// m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
// })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
// ga('create', 'UA-69931401-1', 'auto');
// ga('send', 'pageview');
// }</script></body></html>