You can obtain the current API revision of libevl either at compilation time using the
value of the __EVL__
macro defined in the <evl/evl.h>
main header
file, or dynamically by calling evl_get_version().
Amend the behavior of calling evl_usleep() with a zero delay value, which now yields no effect instead of returning EINVAL.
Finalize the proxy interface with the addition of evl_read_proxy(). For consistency, evl_send_proxy() was renamed to evl_write_proxy() in the same move.
proxy_{out/err}fd values are now accessible via function calls, respectively evl_stdout() and evl_stderr() to make them non-mutable once initialized and prevent name clashes.
Finally, introduce evl_eprintf() to format output to stderr.
Add support for read/write locks. Add DEFINE_EVL_*() macro helpers using static initializers for mutex, event, semaphore and flag group.
Extended event flags API with conjunctive/disjunctive wait modes and support for broadcast, semaphore flush. Removal of the EVL shim layer over the POSIX interface.
Align on thread status bit renames from ABI 31.
Add lockless interface for heaps.
Export a system interface to low-level core services.
Removal of the tube API. See below.
The tube API has a number of implementation issues, which makes it unsuitable for mp/mc usage. ABA-safety is not even there for sp/sc usage either.
Instead of painfully fixing a broken design, libevl r30 introduces a lighweight, lock-free mp/mc FIFO ring data structure based on Ruslan Nikolaev’s Scalable Circular Queue (double-width CAS variant): http://drops.dagstuhl.de/opus/volltexte/2019/11335/pdf/LIPIcs-DISC-2019-28.pdf https://github.com/rusnikola/lfqueue.git
Functionally, everything that was possible with tubes can be implemented using rings. With the added bonus that rings are correct.
As a result, the tube API is officially deprecated, and will go away in libevl r31.
Introduces the socket interface:
oob_recvmsg() to receive a message in out-of-band mode.
oob_sendmsg() to send a message in out-of-band mode.
The regular socket(2) call as extended by ABI 26 is capable of creating oob-capable sockets when receiving the SOCK_OOB type flag, so there is no EVL-specific call for this operation.
Enables HM support for threads. Since ABI 23, the core is able to channel EVL_T_WOSS, EVL_T_WOLI and EVL_T_WOSX error notifications (SIGDEBUG_xxx) through the thread observable component if present. Introduce the EVL_T_HMSIG and EVL_T_HMOBS mode bits for configuring the HM notification source(s) of a thread with evl_set_thread_mode().
SIGDEBUG_xxx codes are renamed to EVL_HMDIAG_xxx diag codes, so that we have a single nomenclature for these errors regardless of whether threads are notified via SIGDEBUG or their observable component.
Introduces the API changes for supporting the new Observable element:
adds evl_subscribe() and evl_unsubscribe() to the thread API.
adds the evl_create_observable(), evl_update_observable() and evl_read_observable() services for the new Observable API.
allows to pass an opaque data to evl_add_pollfd() and
evl_mode_pollfd(), which is
returned into the struct evl_poll_event
descriptor.
Adds evl_set_thread_mode() and evl_clear_thread_mode().
Adds evl_unblock_thread() and evl_demote_thread().
Adds evl_yield().
Element visibility is introduced, as a result:
Most element classes provides a new long-form evl_create_*() call,
in order to receive creation flags. Currently, the visibility
attribute of elements is the only flag supported (see
EVL_CLONE_PRIVATE
, EVL_CLONE_PUBLIC
). The additional creation
calls are evl_create_event(),
evl_create_flags(),
evl_create_mutex(),
evl_create_proxy(),
evl_create_sem() and
evl_create_xbuf(). Likewise, the
new evl_attach_thread() and
evl_detach_thread() calls
receive attachment and detachment flags for
threads. evl_attach_self() is now
equivalent to attaching a private thread by default, unless the
thread name says otherwise. evl_detach_self() is unchanged.
All evl_new_*() calls become shorthands to their respective evl_create_*() counterparts, picking reasonable default creation parameters for the new element, including private visibility (unless overriden by the leading slash rule explained in this document).
All long-form evl_new_*_any() calls have been removed from the API. Applications should use the corresponding evl_create_*() call instead.
evl_new_proxy() creates a proxy element with no write granularity by default, which caused this this parameter to be dropped from the call signature. Applications should use evl_create_proxy() to specify a non-default granularity.
evl_new_xbuf() creates a cross-buffer element with identically sized input and output buffers by default, which caused one of the two size parameters to be dropped from the call signature. Applications should use evl_create_xbuf() to specify distinct sizes for input and output.
All former long-form static initializers EVL_*_ANY_INITIALIZER() have been renamed EVL_*_INITIALIZER(), dropping the former short-form (if any). For instance, EVL_MUTEX_ANY_INITIALIZER() has been renamed EVL_MUTEX_INITIALIZER(), with an additional parameter for mentioning both the lock type and visibility attribute.
Selecting the lock type of a mutex is now done using the
evl_create_mutex() call, ORing
either EVL_MUTEX_NORMAL
or EVL_MUTEX_RECURSIVE
into the creation
flags. This method replaces the type argument to the former
evl_new_mutex_any() call.
For naming consistency, evl_sched_control() was renamed evl_control_sched().