//
// Copyright (c) 2014-2015,2017,2024 LAAS/CNRS
// All rights reserved.
//
// Redistribution and use  in source  and binary  forms,  with or without
// modification, are permitted provided that the following conditions are
// met:
//
//   1. Redistributions of  source  code must retain the  above copyright
//      notice and this list of conditions.
//   2. Redistributions in binary form must reproduce the above copyright
//      notice and  this list of  conditions in the  documentation and/or
//      other materials provided with the distribution.
//
//                                      Anthony Mallet on Wed Jul 16 2014
//
:xrefstyle: short

ifdef::sidebartoc[]
include::_Sidebar.adoc[]
endif::[]

Genom component model
---------------------

=== Overview

A Genom component is a server that provides a number of services and
communicates through data ports with other components in the system.  Services
are asynchronous (meaning that they can be started without waiting for
termination).

The execution of a service is controlled by a finite state automaton and an
optional clock. Several services can be active in parallel in the same
component, using distinct execution tasks or not.

A running service can be observed and controlled from outside the component. In
particular it can be interrupted if needed, and the programmer can provide code
to handle the interruption in a clean and safe way (for example offering a
clean stop of an ongoing motor motion).

The algorithms executed by a service must be decomposed in chunks whose
execution cannot be interrupted, and thus should not run for too long
(otherwise compromising the ability to interrupt it). Those chunks form the
basic code elements manipulated by Genom and are called "codels".

Genom provides an exception mechanism to handle errors that can be detected
during codel execution. Genom exceptions can transmit any kind of data
available to the codels to describe the error to the component that called the
service, making it possible to perform a diagnostic of the error, and
eventually to recover from it.

=== Architecture

Each component is a specialization of the generic architecture shown in
<<component>>. Individual elements are described hereafter.

.Generic component architecture
[#component]
image::model/component.svg[Generic component architecture,align=center]

IDS:: The `Internal Data Structure` is a collection of typed data, private to
the component and not visible in its public interface. It allows to share
parameters, computed values or state variables between codels (see below) of
the component implementation, much as global variables would do. Component
entities that need to read or write members of the IDS must specify them
individually in their argument list, so that a proper synchronization between
different threads of the component can be achieved automatically on behalf of
the user, typically by using system mutex and locking primitives.

Ports:: They describe structured data that are part of the component public
interface and allow components to export (`out port`) or asynchronously import
data (`in port`) to or from other components. Ports are named resources,
accessed in an atomic way, so that contained data are always
consistent. Components accessing these data declare them in the argument list
of their services, so that automatic handling with respect to the underlying
middleware can be achieved on behalf of the user.

Services:: Services are procedures taking arguments and returning values, also
part of the component public interface. They represent the core functionality
of a component and implement the user algorithms. Depending on their
characteristics, services fall into three subcategories that are part of their
definition: _attribute_, _function_ and _activity_.

  Attributes::: are accessors for the `IDS` members that need to be exposed
  publicly without further algorithmic processing but possibly filtered by a
  validation procedure.  This is typically used for setting or getting the
  value of a parameter or a group of parameters used by others algorithms
  implemented by other services.  _attributes_ services are considered to have
  zero processing time (or take a negligible amount of time in practice).

  Functions::: are used to implement simple procedures that are meant to
  produce a result immediately and not remain in a running state once their
  execution is done.  For this reason, they are typically invoked
  _synchronously_ and are not expected to linger.

  Activities::: implement complex procedures that are meant to run for a long
  time.  They usually do not provide a result directly but rather as a side
  effect of their execution, by performing some actions through connected
  hardware, continuously executing an algorithm on incoming data retrieved by
  input ports or producing data exported to output ports. They are typically
  invoked _asynchronously_ and modify the component state.  Because of their
  long-lasting nature, activities are _interruptible_, at the client request,
  or as a specified side effect of another service starting.

Requests, Reports, Exceptions:: Components provide a remote procedure call
interface that enables external clients to request the execution of services at
any time.  This is implemented via a request-reply protocol specific to the
middleware and transparent to the user. In addition to any data computed and
returned as a result of the service execution, the reports always contain the
status of the execution: in case of failure or anomalous execution, an
_exception_ is raised. _Exceptions_ are user-defined types, like any other data
type, that describe precisely the nature of the execution error and allows
error recovery in the client invoking the failing service.

Control Task:: It is an internal unit of execution (typically a thread) that
manages in an infinite loop the control flow of a component by processing
incoming _requests_ made by external clients, triggering the execution of the
subroutines associated with the requests and sending corresponding _reports_
once the execution is complete. The control task is directly in charge of
executing the user code associated with _attributes_ and _functions_ services,
while it delegates the execution of _activities_ to _execution tasks_ (see
below). All components have exactly one _control task_.

Execution Task(s):: They are also a cyclic internal unit of execution.  They
execute the user code associated with _activities_ that they are in charge of
and are driven by the control task. At the user choice, they can be periodic or
run freely, depending on the algorithms that they are to run.  They can also
optionally execute a particular activity, named _permanent activity_, during
their whole lifecycle instead of just as the result of a user request.  A
component can have from zero to many execution tasks.

Codels:: A codel (``code element'') is a function implementing some user
processing. It is specified with:
* the name of a C function (implementing C or C++ code),
* the arguments to pass when calling it (from or to the `IDS`, in or out ports
  data and service input parameters or output values) and
* a list of allowed return values. The returned values are used by the activity
  automata, defined in the next paragraph.

Activity Automaton:: _Activities_ are modeled with an automaton that breaks
down the processing into different _states_.  Each state is associated with a
_codel_. The execution of that _codel_ leads to (yields) the next state in the
automaton, to execute immediately, or in the next period if this next state
name is prefixed with `pause`.


=== Summary

In order to build a GenoM component, the programmer has to write two kind of
inputs:

 * the formal description of the component, describing the tasks, services,
   input and output ports, activities automaton and data types.
 * the code of the codels that implements the algorithms of the services.

Genom processes these inputs with a middleware specific template to generate
several outputs:

 * the source code of the component itself, interfaced with the codels and the
   communication layer for the selected middleware bound to all external
   libraries that the component may depend upon.
 * a set of client libraries that use the chosen middleware to interact with
   the component. The API of those libraries are themselves middleware
   independent, making it possible to control component with middleware
   independent code.

Note that Genom templates can potentially generate any kind of source code,
such as a graphical test program or even documentation, so Genom itself is
highly extensible.
