Link Search Menu Expand Document

Threading and Concurrency Model

Libertas-OS is an Operating System for IoT. Each public function represents a potential executable on the Libertas-OS.

Each Thing-App task is equivalent to a running process with a public function as an entry point and a list of arguments from user input through Smartphone GUI.

Libertas adopts coroutine based threading model because this model is the best fit for IoT use cases, even for applications demanding hard real-time guarantee.

Thread Control APIs

LibertasThread

type LibertasThread = number;

Libertas_NewThread

function Libertas_NewThread(func: Function, ...args: any[]): LibertasThread

Libertas_ExitThread

function Libertas_ExitThread(thread?: LibertasThread): void

Omni Paradigm Design

The pursuit of simplicity is never enough. We designed the programming model of Libertas-OS to support all paradigms:

Never-ending Simplicity

There is no reason to use imperative programming for device and I/O control. Even though we support both paradigms, we strike a balance for further simplicity.

  • Only reactive paradigm is offered for device and I/O.
  • Imperative is intended for long-running jobs or simple control sequences.

One Paradigm Per Thread

Imperative and reactive APIs can not be mixed within a single thread.

There is no reason to have more than one reactive thread in a task. It won’t improve efficiency or response latency.

Since imperative is designed for simple control sequences or long-running jobs, sometimes having more than one imperative may simplify programming.

Imperative API

Two wait functions put the current thread in a waiting state.

Libertas_Wait

function Libertas_Wait(milliSeconds?: number): void;

Libertas_WaitUntil

function Libertas_WaitUntil(timeout: number): void;

Once a thread is waiting, it won’t return from the “wait” call until the specified timeout is reached or the thread is notified (woke up) from another thread.

Libertas_NotifyThread

function Libertas_NotifyThread(thread: LibertasThread): void;

Yield a Thread

Libertas Thing-App thread is coroutine based. It only supports cooperative multi-tasking. A thread won’t be preemptively context-switched using timeslice. Instead, a thread must willingly yield the execution so that another thread will have a chance to run.

Libertas_Yield

function Libertas_Yield(): void;

Note a long-running job must periodically yield the execution. Otherwise, it may take too much time to run, and it will block other threads from responding to timely events.

Libertas will kill a task if it is not responsive within a certain period (1 second).

Libertas_Yield works with both imperative and reactive paradigm. However, a reactive code shall take little time to run because it will block subsequent incoming events. That is exactly why we introduced the imperative waiting/notification model for long-running jobs. Designing the Thing-App to coordinate the jobs to ensure system responsiveness is essential.

Reactive API

Reactive API follows the subscribe/callback model.

The LibertasEvent Object

LibertasEvent is used in some device callback functions to encapsulate complex data structures.

Use Cases

The following features only support the reactive model. Read the chapters for details.

The Libertas_WaitReactive Call

After registering the callback functions. Libertas_WaitReactive must be the last call of a reactive thread. Internally, the call will drive the event loop of the entire Thing-App task.

A Thing-App task shall only have one reactive thread which makes a call to Libertas_WaitReactive at last. Having more than one reactive thread will not improve.