Event Queues
============

An event queue allows a task to serialize incoming events and simplify
event processing. Events are stored in a queue and a task removes and
processes an event from the queue. An event is processed in the context
of this task. Events may be generated by OS callouts, interrupt handlers, 
and other tasks.

Description
---------------

Mynewt's event queue model uses callback functions to process events.
Each event is associated with a callback function that is called to
process the event. This model enables a library package, that uses
events in its implementation but does not have real-time timing
requirements, to use an application event queue instead of creating a
dedicated event queue and task to process its events. The callback
function executes in the context of the task that the application
creates to manage the event queue. This model reduces an application's
memory requirement because memory must be allocated for the task's stack
when a task is created. A package that has real-time timing requirements
and must run at a specific task priority should create a dedicated event
queue and task to process its events.

In the Mynewt model, a package defines its events and implements the
callback functions for the events. A package that does not have
real-time timing requirements should use Mynewt's default event queue
for its events. The callback function for an event from the Mynewt
default event queue is executed in the context of the application main
task. A package can, optionally, export a function that allows an
application to specify the event queue for the package to use. The 
application task handler that manages the event queue simply pulls events 
from the event queue and executes the event's callback function in its context.

A common way that Mynewt applications or packages process events from an
event queue is to have a task that executes in an infinite loop and
calls the :c:func:`os_eventq_get()` function to dequeue and return the event
from the head of the event queue. The task then calls the event callback
function to process the event. The :c:func:`os_eventq_get()` function puts the
task in to the ``sleeping`` state when there are no events on the queue.
(See :doc:`../context_switch/context_switch` for more
information on task execution states.) Other tasks (or interrupts) call
the :c:func:`os_eventq_put()` function to add an event to the queue. The
:c:func:`os_eventq_put()` function determines whether a task is blocked
waiting for an event on the queue and puts the task into the
``ready-to-run`` state.

A task can use the :c:func:`os_eventq_run()` wrapper function that calls the
:c:func:`os_eventq_get()` function to dequeue an event from the queue and then
calls the event callback function to process the event.
Note:

-  Only one task should consume or block waiting for events from an
   event queue.
-  The OS callout subsystem uses events for timer expiration notification.

Example
-------

Here is an example of using an event from the BLE host: 

.. code:: c

    static void ble_hs_event_tx_notify(struct os_event *ev);

    /** OS event - triggers tx of pending notifications and indications. */
    static struct os_event ble_hs_ev_tx_notifications = {
        .ev_cb = ble_hs_event_tx_notify,
    };

    
API
----

.. doxygengroup:: OSEvent
    :members:
    :content-only:
