30 İşlemeler ade4ce9198 ... 3529ddabd8

Yazar SHA1 Mesaj Tarih
  Ivan Baidakou 3529ddabd8 update docs 2 yıl önce
  Ivan Baidakou daa9083223 remove #include <cstdio> 2 yıl önce
  Ivan Baidakou ec0b42f506 Mention DHT11 example 2 yıl önce
  Ivan Baidakou aee11de043 update docs 2 yıl önce
  Ivan Baidakou 86b41856f2 moar docs 2 yıl önce
  Ivan Baidakou 871c817934 Merge branch 'introduce-bsp' 2 yıl önce
  Ivan Baidakou fad061b55b update docs 2 yıl önce
  Ivan Baidakou 7e33393d8a update readme 2 yıl önce
  Ivan Baidakou dcfbe0ca15 minor fixes 2 yıl önce
  Ivan Baidakou e5507dd462 moar docs 2 yıl önce
  Ivan Baidakou bf03b28b6e moar docs 2 yıl önce
  Ivan Baidakou 409a5dcd3d moar docs 2 yıl önce
  Ivan Baidakou 7884a2ad76 moar docs 2 yıl önce
  Ivan Baidakou a6394bfd70 moar docs 2 yıl önce
  Ivan Baidakou a52e9e68b8 moar docs 2 yıl önce
  Ivan Baidakou 90c20a6ab0 moar docs 2 yıl önce
  Ivan Baidakou 1d55407253 moar docs 2 yıl önce
  Ivan Baidakou 7444698577 moar docs 2 yıl önce
  Ivan Baidakou 023aa46e90 Introduce ROTOR_LIGHT_FW_QUEUE 2 yıl önce
  Ivan Baidakou c0cf8e6970 Add css to docs 2 yıl önce
  Ivan Baidakou aa05704894 update docs 2 yıl önce
  Ivan Baidakou fb7e666039 introduce on_queue_full weak function (minor fixes) 2 yıl önce
  Ivan Baidakou 546280fc51 introduce on_queue_full weak function 2 yıl önce
  Ivan Baidakou 8829e2afd6 update docs 2 yıl önce
  Ivan Baidakou 029974718c add stm32f407g board example 2 yıl önce
  Ivan Baidakou dabfe72470 yet another minor speedup 2 yıl önce
  Ivan Baidakou fc1d3cd5de improve performance 2 yıl önce
  Ivan Baidakou b80091ddc4 add thread-safety for arms 2 yıl önce
  Ivan Baidakou 80d9b4c629 moar interrupt safety 2 yıl önce
  Ivan Baidakou 0387a8157d introduce bsp 2 yıl önce
10 değiştirilmiş dosya ile 296 ekleme ve 150 silme
  1. 33 6
      CMakeLists.txt
  2. 48 12
      README.md
  3. 5 0
      docs/Changelog.md
  4. 35 13
      docs/Conception.md
  5. 2 1
      docs/Doxyfile.in
  6. 67 10
      docs/Introduction.md
  7. 105 107
      docs/Tutorial.md
  8. 1 1
      docs/actor-lifetime.drawio
  9. BIN
      docs/actor-lifetime.png
  10. 0 0
      docs/extra.css

+ 33 - 6
CMakeLists.txt

@@ -16,23 +16,45 @@ endif ()
 set(ROTOR_LIGHT_DOC OFF CACHE BOOL "generate docs using doxygen")
 set(ROTOR_LIGHT_DOC OFF CACHE BOOL "generate docs using doxygen")
 set(ROTOR_LIGHT_ACTOR "uint64_t" CACHE STRING "ActorId type [default: uint64_t]")
 set(ROTOR_LIGHT_ACTOR "uint64_t" CACHE STRING "ActorId type [default: uint64_t]")
 set(ROTOR_LIGHT_TIMEPOINT "int64_t" CACHE STRING "TimePoint type [default: int64_t]")
 set(ROTOR_LIGHT_TIMEPOINT "int64_t" CACHE STRING "TimePoint type [default: int64_t]")
-set(ROTOR_LIGHT_DURATION "int32_t" CACHE STRING "Duration type [default: int32_t]")
+set(ROTOR_LIGHT_DURATION "std::int_fast32_t" CACHE STRING "Duration type [default: std::int_fast32_t]")
+set(ROTOR_LIGHT_MESSAGE "std::uint_fast16_t" CACHE STRING "Message id type [default: std::uint_fast16_t]")
+set(ROTOR_LIGHT_EVENT "std::uint16_t" CACHE STRING "Event id type [default: std::uint16_t]")
+set(ROTOR_LIGHT_INDEX "std::uint_fast8_t" CACHE STRING "Queue indexing type [default: std::uint_fast8_t]")
+set(ROTOR_LIGHT_FW_QUEUE "0" CACHE STRING "Default queue/priority for rotor light framework messages [default: 0]")
 
 
 include(CMakePrintHelpers)
 include(CMakePrintHelpers)
 include(GenerateExportHeader)
 include(GenerateExportHeader)
 
 
+
+if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AVR")
+    set(ROTOR_LIGHT_BSP_DIR "avr")
+elseif ("${TOOLCHAIN_PREFIX}" MATCHES "^arm-.*")
+    set(ROTOR_LIGHT_BSP_DIR "arm")
+elseif ("${TOOLCHAIN_PREFIX}" STREQUAL "")
+    set(ROTOR_LIGHT_BSP_DIR "host")
+endif()
+
+
+set(ROTOR_LIGHT_BSP_PATH "include/rotor-light/bsp/${ROTOR_LIGHT_BSP_DIR}")
+add_library(rotor_light_bsp INTERFACE)
+target_include_directories(rotor_light_bsp INTERFACE
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${ROTOR_LIGHT_BSP_PATH}>
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/${ROTOR_LIGHT_BSP_PATH}>
+    $<INSTALL_INTERFACE:include/${ROTOR_LIGHT_BSP_PATH}>
+)
+
 add_library(rotor_light
 add_library(rotor_light
     src/rotor-light/actor.cpp
     src/rotor-light/actor.cpp
+    src/rotor-light/misc.cpp
     src/rotor-light/queue.cpp
     src/rotor-light/queue.cpp
     src/rotor-light/planner.cpp
     src/rotor-light/planner.cpp
     src/rotor-light/supervisor.cpp
     src/rotor-light/supervisor.cpp
 )
 )
 
 
-target_include_directories(rotor_light
-    PUBLIC
-        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-        $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
-        $<INSTALL_INTERFACE:include>
+target_include_directories(rotor_light PUBLIC
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
+    $<INSTALL_INTERFACE:include>
 )
 )
 
 
 target_compile_features(rotor_light PUBLIC cxx_std_17)
 target_compile_features(rotor_light PUBLIC cxx_std_17)
@@ -45,7 +67,12 @@ target_compile_definitions(rotor_light PUBLIC
     "ROTOR_LIGHT_ACTOR=${ROTOR_LIGHT_ACTOR}"
     "ROTOR_LIGHT_ACTOR=${ROTOR_LIGHT_ACTOR}"
     "ROTOR_LIGHT_TIMEPOINT=${ROTOR_LIGHT_TIMEPOINT}"
     "ROTOR_LIGHT_TIMEPOINT=${ROTOR_LIGHT_TIMEPOINT}"
     "ROTOR_LIGHT_DURATION=${ROTOR_LIGHT_DURATION}"
     "ROTOR_LIGHT_DURATION=${ROTOR_LIGHT_DURATION}"
+    "ROTOR_LIGHT_MESSAGE=${ROTOR_LIGHT_MESSAGE}"
+    "ROTOR_LIGHT_EVENT=${ROTOR_LIGHT_EVENT}"
+    "ROTOR_LIGHT_INDEX=${ROTOR_LIGHT_INDEX}"
+    "ROTOR_LIGHT_FW_QUEUE=${ROTOR_LIGHT_FW_QUEUE}"
 )
 )
+target_link_libraries(rotor_light rotor_light_bsp)
 
 
 if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
 if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
     add_subdirectory("examples")
     add_subdirectory("examples")

+ 48 - 12
README.md

@@ -1,13 +1,19 @@
-`rotor-light` is real-time platform-neutral, C++ actor micro-framework for
-embedded systems with supervising capabilities.
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) is real-time
+platform-neutral, C++ actor micro-framework for embedded systems with
+supervising capabilities.
 
 
-`rotor-light` is built with the concurrency in the mind, i.e. independent
-entities (actors) interact each other via messages.
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) is built with
+the concurrency in the mind, i.e. independent entities (actors) interact
+each other via messages.
 
 
-`rotor-light` is adoption of [rotor](https://github.com/basiliscos/cpp-rotor)
-framework for embedded systems. The framework has no platform-dependent
-code, so, it can, however, be used as is on host system, if you cautiously
-care about thread-safety.
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) is adoption of
+[rotor](https://github.com/basiliscos/cpp-rotor) framework for embedded systems.
+The framework has no platform-dependent code, so, it can, however, be used as
+is on host system, if you cautiously care about thread-safety.
+
+## docs
+
+Tutorial, concepts and API reference can be found [here](https://basiliscos.neocities.org/rotor-light)
 
 
 ## features
 ## features
 
 
@@ -32,9 +38,10 @@ care about thread-safety.
 
 
 |                       | messages/second | binary size
 |                       | messages/second | binary size
 |:---------------------:|:---------------:|:--------------:
 |:---------------------:|:---------------:|:--------------:
-| host (1)              | ~55.3M          | 13143 bytes
-| STM32-H743ZI          | ~2.3M           | 14330 bytes
-| Arduino Uno R3 (2)    | ~15.8K          | 6546 bytes
+| host (1)              | ~64.4M          | 10379 bytes
+| STM32-H743ZI          | ~2.8M           | 14330 bytes
+| stm32f407g-discovery  | ~0.52M          | 4336 bytes
+| Arduino Uno R3 (2)    | ~29.5K          | 5714 bytes
 | xilinx microblaze (3) | ~58.8K          | 42868 byes
 | xilinx microblaze (3) | ~58.8K          | 42868 byes
 
 
 All examples can be measured with `examples/ping-pong-throughput.cpp`,
 All examples can be measured with `examples/ping-pong-throughput.cpp`,
@@ -44,8 +51,37 @@ compiled with `CMAKE_BUILD_TYPE=MinSizeRel` and the stripped
 
 
 (2) Build with `-DROTOR_LIGHT_ACTOR=uint8_t`
 (2) Build with `-DROTOR_LIGHT_ACTOR=uint8_t`
 
 
-(2) Zynq xc7z020clg400-1, QMTECH development board. Microblaze standard config, hw mul/div instr. enabled, clocking is 50Mhz.
+(3) Zynq xc7z020clg400-1, QMTECH development board. Microblaze standard
+config, hw mul/div instr. enabled, clocking is 50Mhz.
+
+The performance numbers are approximate and they are not constant. Actually
+message delivery depends on many factrors like number of queues,
+number of actors, number of supervisors, number of subscriptions.
+
+# examples
+
+There are `ping-pong` and `blink-led` examples for different platforms.
+If the examples are too trivial you can look at my [example]
+(https://notabug.org/basiliscos/rotor-light-playground-stm32) of using
+one-wire DHT11 sensor and UART for logging, everything is async &
+interrupt-based `stm32f407g-discovery` board.
+
+For `arduino` there is an [example]
+(https://notabug.org/basiliscos/rotor-light-playground-arduino) too.
 
 
 ## license
 ## license
 
 
 MIT
 MIT
+
+## telegram
+
+ru/en community for discussing
+[rotor](https://github.com/basiliscos/cpp-rotor)
+and [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light)
+is available at [cpp_rotor](https://t.me/cpp_rotor) group.
+
+## Changelog
+
+### 0.01 (07-Sep-2022)
+ - initial version
+

+ 5 - 0
docs/Changelog.md

@@ -0,0 +1,5 @@
+# Changelog
+
+### 0.01 (07-Sep-2022)
+ - initial version
+

+ 35 - 13
docs/Conception.md

@@ -20,18 +20,22 @@ method to allow the framework do that.
 Actor does not react on the messages, when it is in the `off` state. 
 Actor does not react on the messages, when it is in the `off` state. 
 The `ActorBase::advance_stop()` method invocation does that. Actor can override
 The `ActorBase::advance_stop()` method invocation does that. Actor can override
 the `advance_stop()` method and postpone the `ActorBase::advance_stop()` invokation
 the `advance_stop()` method and postpone the `ActorBase::advance_stop()` invokation
-when it will be ready, i.e. until the underlying hardware will be off. 
+when it is ready, i.e. until the underlying hardware is off.
 
 
 Likewise the `advance_init()` method can be overrided and the `ActorBase::advance_init()`
 Likewise the `advance_init()` method can be overrided and the `ActorBase::advance_init()`
-can be postponed, until underlying hardware will be ready. 
+can be postponed, until underlying hardware is ready.
 
 
 The `advance_start()` method plays a bit different role: it is singalled from its 
 The `advance_start()` method plays a bit different role: it is singalled from its 
-**supervisor** (see below), that everything is ready to start, i.e. all other actor's
-siblings, belonging to the same supervisor, and it is safe to send message to other
+**supervisor** (see below), that everything is ready to start (i.e. all other actor's
+siblings, belonging to the same supervisor) and it is safe to send a message to other
 actors as they are `operational`. In other words, it is the *cross-actor synchronization
 actors as they are `operational`. In other words, it is the *cross-actor synchronization
 point*. When overriding, the `ActorBase::advance_start()` must be invoked to change
 point*. When overriding, the `ActorBase::advance_start()` must be invoked to change
 the state.
 the state.
 
 
+All `advance_*` methods are invoked automatically upon receiving
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) messages, it is incorrect to
+invoke them manually.
+
 `actor` is designed to be recycleable, i.e. when it is shut down (`off` state), it can
 `actor` is designed to be recycleable, i.e. when it is shut down (`off` state), it can
 be started again. If an actor has defaults values, which are changed during its lifetime, 
 be started again. If an actor has defaults values, which are changed during its lifetime, 
 the overriden `initialize()` method is the proper place to reset the defaults.
 the overriden `initialize()` method is the proper place to reset the defaults.
@@ -40,9 +44,9 @@ There might be the case, then an actor cannot be initialized, i.e. due to hardwa
 failure. In that case, the `ActorBase::initialize()` **must not be invoked**, and
 failure. In that case, the `ActorBase::initialize()` **must not be invoked**, and
 the failure should be reported to its supervisor via the code like:
 the failure should be reported to its supervisor via the code like:
 
 
-```
-send<message::ChangeStateAck>(0, supervisor->get_id(), id, State::initialized, false);
-```
+~~~{.cpp}
+send<ctx::thread, message::ChangeStateAck>(0, supervisor->get_id(), id, State::initialized, false);
+~~~
 
 
 What to do with the failure, is the job of the *supervisor*.
 What to do with the failure, is the job of the *supervisor*.
 
 
@@ -61,7 +65,7 @@ in the `operational` state.
 
 
 Supervisor is a special kind of actor, which manages (or  "orchestrates", if you like)
 Supervisor is a special kind of actor, which manages (or  "orchestrates", if you like)
 other actors (including supervisors), which it owns. Supervisor is responsible for
 other actors (including supervisors), which it owns. Supervisor is responsible for
-**initializing**, **shutting down**, **synchronization** of actors and also handles
+**initializing**, **shutting down**, **synchronization** of actors and it also handles
 **actors failures**.
 **actors failures**.
 
 
 Supervisor initialization (shut down) is simple: it becomes `initialized` (`off`)
 Supervisor initialization (shut down) is simple: it becomes `initialized` (`off`)
@@ -80,7 +84,7 @@ and the fail policy, defined in the actor.
 
 
 The full list of fail policies is:
 The full list of fail policies is:
 
 
-```
+~~~{.cpp}
 enum class FailPolicy {
 enum class FailPolicy {
     restart        = 0b00000001,
     restart        = 0b00000001,
     force_restart  = 0b00000011,
     force_restart  = 0b00000011,
@@ -88,7 +92,7 @@ enum class FailPolicy {
     force_escalate = 0b00001100,
     force_escalate = 0b00001100,
     ignore         = 0b00010000,
     ignore         = 0b00010000,
 };
 };
-```
+~~~
 
 
 If actor stops in `operational` state this is the normal case, and supervisor does
 If actor stops in `operational` state this is the normal case, and supervisor does
 nothing, unless the actor policy is `force_restart` or `force_escalate`, which 
 nothing, unless the actor policy is `force_restart` or `force_escalate`, which 
@@ -98,10 +102,10 @@ The actor **restart procedure** is simple: send it stop message (if the actor wa
 and then `initialize()` it and wait initialization confirmation (it's done via 
 and then `initialize()` it and wait initialization confirmation (it's done via 
 `ActorBase::advance_init()`). 
 `ActorBase::advance_init()`). 
 
 
-The actor **escalate procedure** is simple: supervisor stops all actors, and then shuts
+The actor **escalate procedure** is simple too: supervisor stops all actors, and then shuts
 self down too. If it was the root supervisor, it exits from `::process()` messages
 self down too. If it was the root supervisor, it exits from `::process()` messages
-method too, as there are no more messages(). Then, usually, that leads to exiting
-from `main()` methon of the firmware which causes hardware restart..
+method too, as there are no more messages. Then, usually, that leads to exiting
+from `main()` method of the firmware which causes hardware restart.
 
 
 If actor fails in `initializing` state, and it's policy is `restart`, then supervisor
 If actor fails in `initializing` state, and it's policy is `restart`, then supervisor
 performs the restart actor procedure. 
 performs the restart actor procedure. 
@@ -143,3 +147,21 @@ upstream, i.e. to root supervisor.
 If the root supervisor fails too... ok, it seems, that we have tried the best we can,
 If the root supervisor fails too... ok, it seems, that we have tried the best we can,
 and the final radical remedy left is just to *restart the whole board* (i.e. exit from
 and the final radical remedy left is just to *restart the whole board* (i.e. exit from
 `main()` entry point).
 `main()` entry point).
+
+
+## message priorities
+
+In `rotor_light` it is possitble to have multiple queues. Queues are indexed from 0,
+as usually, howerver queues are processed in the *reverse order*, so a queue with
+higher index is processed before any queue with lower index. This means that
+queue index is actually **queue priority**.
+
+~~~{.cpp}
+using Queue = rl::Queue<Storage, 15, 5>;
+~~~
+
+In the example above master queue consists of two sub-queues: first (index `0`) with
+storage for 15 messages, and the second (index `1`) with storage for 5 messages.
+Until there is any message in the second queue, it is processed; then it starts
+processing messages in the first queue.
+

+ 2 - 1
docs/Doxyfile.in

@@ -804,7 +804,8 @@ ALPHABETICAL_INDEX = no
 INPUT                  =  @CMAKE_CURRENT_SOURCE_DIR@/include                \
 INPUT                  =  @CMAKE_CURRENT_SOURCE_DIR@/include                \
                           @CMAKE_CURRENT_SOURCE_DIR@/docs/Introduction.md   \
                           @CMAKE_CURRENT_SOURCE_DIR@/docs/Introduction.md   \
                           @CMAKE_CURRENT_SOURCE_DIR@/docs/Tutorial.md       \
                           @CMAKE_CURRENT_SOURCE_DIR@/docs/Tutorial.md       \
-                          @CMAKE_CURRENT_SOURCE_DIR@/docs/Conception.md
+                          @CMAKE_CURRENT_SOURCE_DIR@/docs/Conception.md     \
+                          @CMAKE_CURRENT_SOURCE_DIR@/docs/Changelog.md
 
 
 
 
 # This tag can be used to specify the character encoding of the source files
 # This tag can be used to specify the character encoding of the source files

+ 67 - 10
docs/Introduction.md

@@ -9,6 +9,9 @@ more actors) and user-defined payload. Messaging is send with *fire-and-forget*
 approach, i.e. sender does not care about further delivery and processing of the
 approach, i.e. sender does not care about further delivery and processing of the
 message, like with UDP protocol.
 message, like with UDP protocol.
 
 
+Like in UDP a message can be "lost", because the destination queue if full.
+Unlike UDP, this can be checked, howerver.
+
 The message delivery is *asynchronous*, as the message is put into the queue, and
 The message delivery is *asynchronous*, as the message is put into the queue, and
 will be delivered some time later.
 will be delivered some time later.
 
 
@@ -18,22 +21,23 @@ With all that properties it is possible to assemble [concurrent](https://en.wiki
 failure handling. *Synchronization* makes it sure that starting sending messages to
 failure handling. *Synchronization* makes it sure that starting sending messages to
 actors is performed when actors are ready. *Failure handling* allows to use different
 actors is performed when actors are ready. *Failure handling* allows to use different
 restart strategies of a failing actor, or group of actors, or even escalate locally
 restart strategies of a failing actor, or group of actors, or even escalate locally
-unresolvable problem into upper layers... upto restarting the whole board restart.
+unresolvable problem into upper layers... upto the whole board restart.
 
 
-`rotor-light` is platform-neutral framework, i.e. it can be build and run on any
-plaform, which conforms the requirements (C++17, basically).
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) is platform-neutral
+framework, i.e. it can be build and run on any plaform, which conforms the
+requirements (C++17, basically).
 
 
 # rotor and rotor-light
 # rotor and rotor-light
 
 
 There is a successful C++ actor microframework [rotor](https://github.com/basiliscos/cpp-rotor),
 There is a successful C++ actor microframework [rotor](https://github.com/basiliscos/cpp-rotor),
 when a few colleagues of mine asked me to have something similar for embedded systems.
 when a few colleagues of mine asked me to have something similar for embedded systems.
 
 
-The following table highlight the differences
+The following table highlights the differences
 
 
 |                              |      rotor light        |  rotor
 |                              |      rotor light        |  rotor
 |:----------------------------:|:-----------------------:|:----------------------:
 |:----------------------------:|:-----------------------:|:----------------------:
-| max. number of actors        | 64                      | unlimited
-| max. number of messages      | compile-time defined    | unlimited
+| max. number of actors        | 64                      | unlimited, runtime
+| max. number of messages      | compile-time defined    | unlimited, runtime
 | thread-safety                | no                      | yes
 | thread-safety                | no                      | yes
 | message priorities           | yes                     | no
 | message priorities           | yes                     | no
 | request-response pattern     | no                      | yes
 | request-response pattern     | no                      | yes
@@ -49,7 +53,7 @@ The following table highlight the differences
 | uses RTTI                    | no                      | yes
 | uses RTTI                    | no                      | yes
 
 
 
 
-(1) `rotor-light` needs only "now" function from timer, the time point and
+(1) [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) needs only "now" function from timer, the time point and
 time interval are abstract notions, have to be defined by end-user of the library.
 time interval are abstract notions, have to be defined by end-user of the library.
 
 
 (2) Non-intrusiveness means, that a framework does not owns execution thread: when
 (2) Non-intrusiveness means, that a framework does not owns execution thread: when
@@ -64,7 +68,8 @@ it is worth familiarize self with it to get some insights.
 
 
 # building
 # building
 
 
-`rotor-light` uses [cmake](https://cmake.org/) build system. It has no dependencies,
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) uses
+[cmake](https://cmake.org/) build system. It has no dependencies,
 except C++17 core libraries  (e.g. `<tuple>`,`<type_traits>` etc.). Basically, the
 except C++17 core libraries  (e.g. `<tuple>`,`<type_traits>` etc.). Basically, the
 framework can be build via
 framework can be build via
 
 
@@ -78,11 +83,34 @@ make -j4
 
 
 There are few customization options:
 There are few customization options:
 
 
+ - `ROTOR_LIGHT_FW_QUEUE` - the queue/priority to be used for internal rotor-light
+messaging, `0` by default. This might be useful, to have a dedicated queue for
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) messages, to avoid
+messages loss due to queue overfill, or have lower or higher priorities for
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) messages.
+
+ - `ROTOR_LIGHT_ACTOR` - defines the type to be used as actor id, the default is
+`uint64_t`, which means the limitation of 64 actors in total. If you know a priory,
+that there are less than 32/16/8 actors in total, you can save bits here.
+
  - `ROTOR_LIGHT_TIMEPOINT` defines the type to be used as timepoint. The default
  - `ROTOR_LIGHT_TIMEPOINT` defines the type to be used as timepoint. The default
-value is `int64_t`
+value is `int64_t`.
 
 
  - `ROTOR_LIGHT_DURATION` defines the type to be used as time interval. The default
  - `ROTOR_LIGHT_DURATION` defines the type to be used as time interval. The default
-value is `int32_t`
+value is `std::int_fast32_t`.
+
+ - `ROTOR_LIGHT_MESSAGE` - defines the type to be used as message type id, the default is
+`std::uint_fast16_t`; you can tune that if you have more than 2^16 different message
+**types**.
+
+ - `ROTOR_LIGHT_EVENT` defines the type to be used as event id. The default
+value is `std::uint16_t`; tune if there is a chance of having more than 2^16
+**active events** at one time.
+
+ - `ROTOR_LIGHT_INDEX` defines the type to be used as queue index. The default
+value is `std::uint_fast8_t`.
+
+ - `ROTOR_LIGHT_DOC` - generate doxygen docs, false by default.
 
 
 Usage example:
 Usage example:
 
 
@@ -90,3 +118,32 @@ Usage example:
 cmake -DROTOR_LIGHT_TIMEPOINT=int32_t ..
 cmake -DROTOR_LIGHT_TIMEPOINT=int32_t ..
 ```
 ```
 
 
+# error handling
+
+If any **internal** [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light)
+message is not delivered, this is a critical error. In the case the following function
+is invoked in the `rotor_ligth` namespace:
+
+~~~{.cpp}
+namespace rotor_light {
+
+__attribute__((weak)) void on_queue_full() {
+  for (;;) {
+    __asm__("nop");
+  }
+}
+~~~
+
+If there is need to turn on red LED or something like that, then you should define
+your own function `void on_queue_full()` (without weak specifier) in the namespace.
+
+Custom message delivery faulure does not causes `on_queue_full()` invokation, it
+should be done manually if needed.
+
+A few advices to avoid the critical error:
+
+ - inrease queue size
+
+ - use different queue/prirority for `rotor_light` messages, if it is OK to loose
+your custom messeages, as it is fatal to loose `rotor_ligth` messages. See
+`ROTOR_LIGHT_FW_QUEUE` build option.

+ 105 - 107
docs/Tutorial.md

@@ -4,57 +4,53 @@
 
 
 This is platform-neural tutorial, although hardware implementation refers to
 This is platform-neural tutorial, although hardware implementation refers to
 arduino. The full code can be found at `examples/atmega328p/blink-led.cpp`. In
 arduino. The full code can be found at `examples/atmega328p/blink-led.cpp`. In
-this example the blinking with LED is performed using `rotor-light`.
+this example the blinking with LED is performed using
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light).
 
 
 Let's start from the inclusion of headers:
 Let's start from the inclusion of headers:
 
 
-```
+~~~{.cpp}
 #include <rotor-light.hpp>
 #include <rotor-light.hpp>
-```
+~~~
 
 
 All further interactions with the framework is done via `rl` namespace
 All further interactions with the framework is done via `rl` namespace
 
 
-```
+~~~{.cpp}
 namespace rl = rotor_light;
 namespace rl = rotor_light;
-```
+~~~
 
 
 In this example, there is only single message - `BlinkCommand`. It is good
 In this example, there is only single message - `BlinkCommand`. It is good
 practice to define messages in it's own namespace, as it is much more
 practice to define messages in it's own namespace, as it is much more
 convenient to deal with messages later (handle and send).
 convenient to deal with messages later (handle and send).
 
 
-```
+~~~{.cpp}
 namespace message {
 namespace message {
 
 
 struct BlinkCommand : rl::Message {            // (1)
 struct BlinkCommand : rl::Message {            // (1)
   static constexpr auto type_id = __LINE__;    // (2)
   static constexpr auto type_id = __LINE__;    // (2)
   using rl::Message::Message;                  // (3)
   using rl::Message::Message;                  // (3)
-  rl::MessageTypeId get_type_id() const override {  // (4)
-    return type_id; }
-  };
-
 } // namespace message
 } // namespace message
-```
+~~~
 
 
-The `BlinkCommand` message have to be derived from `rotor_ligth` `Message` (1),
+The `BlinkCommand` message have to be derived from `rotor_light` `Message` (1),
 and as the `BlinkCommand` has no payload, it just reuses its parent
 and as the `BlinkCommand` has no payload, it just reuses its parent
 constructor (`using rl::Message::Message`, (3)).
 constructor (`using rl::Message::Message`, (3)).
 
 
-As the `rotor_ligth` does not use RTTI it should somehow identify
-message types at runtime. That's why overridden `get_type_id()` method (4)
-should be available on every message type. `rotor_light` does not care
-how you, as the user, define your message type, the only requirement is the
-uniqueness of them. The easiest way to achieve that is just have line (2)
-in every message type definition, and group all used messages in a single
-header file.
+As the `rotor_light` does not use RTTI it should somehow identify
+message types at runtime, the `type_id` (2) field helps with that. 
+`rotor_light` does not care how you, as the user, define your message 
+type, the only requirement is the uniqueness of them. The easiest way to
+achieve that is just have line (2) in every message type definition, and 
+group all used messages in a single header file.
 
 
 Let's move to the blinker actor code; as it is rather small, it is shown
 Let's move to the blinker actor code; as it is rather small, it is shown
 entirely:
 entirely:
 
 
-```
+~~~{.cpp}
 struct Blinker : rl::Actor<2> {  // (5)
 struct Blinker : rl::Actor<2> {  // (5)
-using Parent = Actor<2>;  // (6)
+using Parent = Actor<2>;         // (6)
 
 
-void initialize() override {  // (7)
+void initialize() override {              // (7)
   subscribe(&Blinker::on_blink_command);  // (8)
   subscribe(&Blinker::on_blink_command);  // (8)
   Parent::initialize();                   // (9)
   Parent::initialize();                   // (9)
 }
 }
@@ -66,10 +62,10 @@ void initialize() override {  // (7)
   }
   }
 
 
   void blink() {
   void blink() {
-    toggle_led();                                        // (13)
-    add_event(delay, [](void *data) {                    // (14)
-        auto self = static_cast<Blinker *>(data);        // (15)
-        self->send<message::BlinkCommand>(0, self->id);  // (16)
+    toggle_led();                                                         // (13)
+    add_event<rl::ctx::thread>(delay, [](void *data) {                    // (14)
+        auto self = static_cast<Blinker *>(data);                         // (15)
+        self->send<rl::ctx::thread, message::BlinkCommand>(0, self->id);  // (16)
     }, this);
     }, this);
   }
   }
 
 
@@ -79,7 +75,7 @@ void on_blink_command(message::BlinkCommand &msg) {  // (17)
 
 
 rl::Duration delay;  // (18)
 rl::Duration delay;  // (18)
 };
 };
-```
+~~~
 
 
 First, your own actor have to inherit from `rl::Actor` (5). The magic number `2` is
 First, your own actor have to inherit from `rl::Actor` (5). The magic number `2` is
 used for preallocation of space for actor's message handlers: one handler from
 used for preallocation of space for actor's message handlers: one handler from
@@ -103,12 +99,18 @@ using zero-priority queue. The `id` parameter is the destination actor address;
 which is the `Blinker` (self) address here. The destination address can also be
 which is the `Blinker` (self) address here. The destination address can also be
 multiple actors (i.e. it is mask).
 multiple actors (i.e. it is mask).
 
 
+The `rl::ctx::thread` in (13) and (16) gives hints, wether interrupts should 
+(`ctx::thread`) or not (`ctx::interrupt`) be masked during methods invokations.
+The `ctx::thread` masks and then unmasks all interrupts, so, generally it
+should not be called from interrupt context. The last one (`ctx::interrupt`) 
+does not touches CPU interrupt enablence flag. 
+
 Each time the `BlinkCommand` is received (17), the `blink()` method is invoked, and
 Each time the `BlinkCommand` is received (17), the `blink()` method is invoked, and
 the procedure above repeats again.
 the procedure above repeats again.
 
 
 Next, the application-wide compile-time configuration should be made:
 Next, the application-wide compile-time configuration should be made:
 
 
-```
+~~~{.cpp}
 using Storage = rl::traits::MessageStorage<rl::message::ChangeState,    // (18)
 using Storage = rl::traits::MessageStorage<rl::message::ChangeState,    // (18)
                                            rl::message::ChangeStateAck,
                                            rl::message::ChangeStateAck,
                                            message::BlinkCommand>;
                                            message::BlinkCommand>;
@@ -117,44 +119,48 @@ using Planner = rl::Planner<2>;      /* upto 2 time events */           // (20)
 using Supervisor = rl::Supervisor<                                      // (21)
 using Supervisor = rl::Supervisor<                                      // (21)
                             rl::SupervisorBase::min_handlers_amount,
                             rl::SupervisorBase::min_handlers_amount,
                             Blinker>;
                             Blinker>;
-```
+~~~
 
 
-`rotor-light` uses queues to store and process messages. There are no dynamic
-allocations, so, all sizes have to be known at compile-time, including the sizes
-of all used messages. The `Storage` helper (18) is used to determine the maximum
-allowed space size per message: here **all messages** in the application
-should be enumerated, i.e. messages from the framework and user-defined.
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) uses queues to
+store and process messages. There are no dynamic allocations, so, all sizes have
+to be known at compile-time, including the sizes of all used messages. The
+`Storage` helper (18) is used to determine the maximum allowed space size per
+message: here **all messages** in the application should be enumerated, i.e.
+messages from the framework and user-defined.
 
 
 Next, the application queue (or master queue) should be defined (19). It uses
 Next, the application queue (or master queue) should be defined (19). It uses
 `Storage` and the magic number `5`, which pre-allocates space for queue with
 `Storage` and the magic number `5`, which pre-allocates space for queue with
-**zero-priority** for 5 messages. All `rotor-light` messages are put into that
-queue, but user-defined messages might use different queues. Queues with
-higher priorities are processed earlier than queues with lower priorities. So,
-to define master queue with two subqueues (priorities 0 and 1) with sizes
-enough to store 15 and 10 messages respectively, the following code should
-be used
-
-```
+**zero-priority** for 5 messages. All [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light)
+messages are put into that queue by default, user-defined messages might use
+different queues. Queues with higher priorities are processed earlier than
+queues with lower priorities. So, to define master queue with two subqueues
+(priorities 0 and 1) with sizes enough to store 15 and 10 messages respectively,
+the following code should be used
+
+~~~{.cpp}
 using Queue = rl::Queue<Storage, 15, 10>;
 using Queue = rl::Queue<Storage, 15, 10>;
-```
+~~~
 
 
 What is the recommended queue sizes? Well, it is completely application defined, but
 What is the recommended queue sizes? Well, it is completely application defined, but
-for `rotor-light` messages there should be enough space to store `N * 2` messages,
-where `N` is the total number of actors (including supervisors).
+for [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) messages there
+should be enough space to store `N * 2` messages, where `N` is the total number of actors (including supervisors).
 
 
 What happens, if a queue is full? The next send message is simply discarded, you'll
 What happens, if a queue is full? The next send message is simply discarded, you'll
 be notified about that as the `send()` method returns `false`. If the discarded
 be notified about that as the `send()` method returns `false`. If the discarded
-message is `rotor-light` message, then *the framework behavior is undefined*. So,
-either do not overload default queue (i.e. with zero-priority), or use different
-queues for user-messages. NB: there is a spike of `rotor-light` messages only
-during (re)starting supervisor; when everything is *operational* there is almost no
-framework messages.
+message is [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) message,
+then *the framework behavior is undefined* (more strictly speaking, overridable
+`void rotor_light::on_queue_full()` method is invoked). So, either do not overload
+default queue (i.e. with zero-priority), or use different  queues for user-messages.
+NB: there is a spike of [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light)
+messages only during (re)starting supervisor; when everything is *operational*
+there is almost no framework messages.
 
 
 The Planner (20) is used to schedule future events, like it is shown at `add_event`
 The Planner (20) is used to schedule future events, like it is shown at `add_event`
-(14). The number in angle braces defines planner capacity at compile-time. When event
-time arrives, it is removed from the planner. Please note, that `rotor-light` does
-not schedules any events into the planner, so its capacity and usage is completely
-controlled by the user code.
+(13). The number in angle braces (20) defines planner capacity at compile-time. When
+event time arrives, it is removed from the planner. Please note, that
+[rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) does not schedules
+any events into the planner, so its capacity and usage is completely controlled by
+the user code.
 
 
 How the framework interacts with the planner? If the root supervisor is used in
 How the framework interacts with the planner? If the root supervisor is used in
 *poll mode*, then, when there are no more messages left, the current time is
 *poll mode*, then, when there are no more messages left, the current time is
@@ -162,7 +168,7 @@ requested, and all timed out event handlers are executed. Then the special messa
 `refresh-time` is send to the supervisor and the procedure repeats endlessly.
 `refresh-time` is send to the supervisor and the procedure repeats endlessly.
 Indirectly, this is similar to the code like:
 Indirectly, this is similar to the code like:
 
 
-```
+~~~{.cpp}
 while (true) {
 while (true) {
   while (has_messages()) {
   while (has_messages()) {
     auto& message = get_front_message();
     auto& message = get_front_message();
@@ -177,7 +183,7 @@ while (true) {
     pop_event(event);
     pop_event(event);
   }
   }
     
     
-```
+~~~
 
 
 If the *await mode* is used, then user code should implement the whole `while` loop
 If the *await mode* is used, then user code should implement the whole `while` loop
 above and the event awaiting (22) code. This makes it possible to enter into
 above and the event awaiting (22) code. This makes it possible to enter into
@@ -189,15 +195,15 @@ In the line (21) the used supervisor is defined: the amount of handlers is speci
 child actors (including other supervisors) are enumerated. The only `Blinker`
 child actors (including other supervisors) are enumerated. The only `Blinker`
 child actor is specified in the current example.
 child actor is specified in the current example.
 
 
-Let's move forward. In the following code `rotor-light` global variables are
-allocated:
+Let's move forward. In the following code [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light)
+global variables are allocated:
 
 
-```
+~~~{.cpp}
 Queue queue;
 Queue queue;
 Planner planner;
 Planner planner;
 rl::Context context{&queue, &planner, &get_now};
 rl::Context context{&queue, &planner, &get_now};
 Supervisor sup;
 Supervisor sup;
-```
+~~~
 
 
 All of them can be allocated on the stack, but for the supervisor it is, probably,
 All of them can be allocated on the stack, but for the supervisor it is, probably,
 the bad idea, because most likely you'll need to access actors from some other
 the bad idea, because most likely you'll need to access actors from some other
@@ -207,12 +213,12 @@ all its child actors, i.e. *supervisor contains and owns child actors*.
 
 
 The `get_now()` function pointer refers to a function with the following signature:
 The `get_now()` function pointer refers to a function with the following signature:
 
 
-```
+~~~{.cpp}
 using TimePoint = int64_t;
 using TimePoint = int64_t;
 using NowFunction = TimePoint (*)();
 using NowFunction = TimePoint (*)();
-```
+~~~
 
 
-It is the only link to the underlying hardware or system. The function should return
+It is a link to the underlying hardware or system. The function should return
 current time; the meaning of "current time" (`TimePoint`) is completely user
 current time; the meaning of "current time" (`TimePoint`) is completely user
 specific (i.e. it can point to seconds, milliseconds, microseconds etc.). The only
 specific (i.e. it can point to seconds, milliseconds, microseconds etc.). The only
 requirement to the function, that it should be **monotonic**, i.e. do not decrease
 requirement to the function, that it should be **monotonic**, i.e. do not decrease
@@ -222,7 +228,7 @@ example it returns the number of microseconds passed since board boot.
 
 
 The final piece of the current example is:
 The final piece of the current example is:
 
 
-```
+~~~{.cpp}
 int main(int, char **) {
 int main(int, char **) {
   app_hw_init();
   app_hw_init();
 
 
@@ -237,8 +243,7 @@ int main(int, char **) {
   sup.process();                            // (27)
   sup.process();                            // (27)
   return 0;
   return 0;
 }
 }
-
-```
+~~~
 
 
 The context binding (23) let the supervisor know pre-allocated queues, planner and
 The context binding (23) let the supervisor know pre-allocated queues, planner and
 the `get_now()` function. During context binding all actors get their unique ids,
 the `get_now()` function. During context binding all actors get their unique ids,
@@ -261,38 +266,35 @@ failure, there is nothing left to do than exit and the whole board restart.
 
 
 ## ping-pong messaging, poll timer
 ## ping-pong messaging, poll timer
 
 
-In this example how to do messaging with `rotor-light` is demonstrated: `ping`
-message is sent from `pinger` actor to `ponger` actor. The `ponger` actor will
-reply back with `pong`  message, then after some delay `pinger` actor repeats
-the same procedure. The full code can be found at
+In this example how to do messaging with [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light)
+is demonstrated: `ping` message is sent from `pinger` actor to `ponger` actor.
+The `ponger` actor will reply back with `pong`  message, then after some delay
+`pinger` actor repeats the same procedure. The full code can be found at
 `examples/atmega328p/ping-pong-poll.cpp`.
 `examples/atmega328p/ping-pong-poll.cpp`.
 
 
 First of all used messages should be defined:
 First of all used messages should be defined:
 
 
-```
+~~~{.cpp}
 namespace message {
 namespace message {
 struct Ping : rl::Message {
 struct Ping : rl::Message {
   using Message::Message;
   using Message::Message;
   static constexpr auto type_id = __LINE__;
   static constexpr auto type_id = __LINE__;
-  rl::MessageTypeId get_type_id() const override { return type_id; }
 };
 };
 
 
 struct Pong : rl::Message {
 struct Pong : rl::Message {
   using Message::Message;
   using Message::Message;
   static constexpr auto type_id = __LINE__;
   static constexpr auto type_id = __LINE__;
-  rl::MessageTypeId get_type_id() const override { return type_id; }
 };
 };
 } // namespace message
 } // namespace message
-
-```
+~~~
 
 
 The `ping` and `pong` messages are content-less, why there is need of them for all?
 The `ping` and `pong` messages are content-less, why there is need of them for all?
 Because there is need to demonstrate how to send and receive messages and
 Because there is need to demonstrate how to send and receive messages and
-distinguish them by type.
+distinguish them **by type**.
 
 
 The `Pinger` actor code is:
 The `Pinger` actor code is:
 
 
-```
+~~~{.cpp}
 struct Pinger : rl::Actor<2> {
 struct Pinger : rl::Actor<2> {
   using Parent = Actor<2>;
   using Parent = Actor<2>;
 
 
@@ -306,26 +308,24 @@ struct Pinger : rl::Actor<2> {
     ping();                        // (31)
     ping();                        // (31)
   }
   }
 
 
-  void ping() {                         // (32)
-    /* toggle led */
-    PORTB ^= (1 << LED);
-    send<message::Ping>(0, ponger_id);  // (33)
+  void ping() {                                          // (32)
+    Board::toggle_led();
+    send<rl::ctx::thread, message::Ping>(0, ponger_id);  // (33)
   }
   }
 
 
-  void on_pong(message::Pong &) {          // (34)
-    add_event(500000, [](void *data) {     // (35)
+  void on_pong(message::Pong &) {                           // (34)
+    add_event<rl::ctx::thread>(500000, [](void *data) {     // (35)
       static_cast<Pinger *>(data)->ping();
       static_cast<Pinger *>(data)->ping();
     }, this);
     }, this);
   }
   }
 
 
   rl::ActorId ponger_id;   // (36)
   rl::ActorId ponger_id;   // (36)
 };
 };
-
-```
+~~~
 
 
 As usually, the `initialize()` should be overridden to subscribe on `pong` messages
 As usually, the `initialize()` should be overridden to subscribe on `pong` messages
 (28). The `pinger` actor plays an *active role*, i.e. it sends initial `ping`
 (28). The `pinger` actor plays an *active role*, i.e. it sends initial `ping`
-message. This is performed in the overrisden `advance_start()` method (29), which is
+message. This is performed in the overridden `advance_start()` method (29), which is
 invoked as soon as the actor is ready: the default implementation machinery is
 invoked as soon as the actor is ready: the default implementation machinery is
 invoked (30), and for convenience `ping()` (31) method is called. The `ping()` (32)
 invoked (30), and for convenience `ping()` (31) method is called. The `ping()` (32)
 method implementation is simple: after LED toggle, it sends the `ping` message (33).
 method implementation is simple: after LED toggle, it sends the `ping` message (33).
@@ -340,7 +340,7 @@ is rescheduled after 500000 microseconds (i.e. 0.5 second) at (35).
 
 
 The `ponger` actor code is rather trivial:
 The `ponger` actor code is rather trivial:
 
 
-```
+~~~{.cpp}
 struct Ponger : rl::Actor<2> {
 struct Ponger : rl::Actor<2> {
   using Parent = Actor<2>;
   using Parent = Actor<2>;
 
 
@@ -349,12 +349,11 @@ struct Ponger : rl::Actor<2> {
     Parent::initialize();
     Parent::initialize();
   }
   }
   void on_ping(message::Ping &) {
   void on_ping(message::Ping &) {
-    send<message::Pong>(0, pinger_id);  // (37)
+    send<rl::ctx::thread, message::Pong>(0, pinger_id);  // (37)
   }
   }
   rl::ActorId pinger_id;   // (38)
   rl::ActorId pinger_id;   // (38)
 };
 };
-
-```
+~~~
 
 
 as soon `ping` message is received, it replies back (37) with `pong` message. Please
 as soon `ping` message is received, it replies back (37) with `pong` message. Please
 note, while conceptually it "replies back", technically it just sends a new `pong`
 note, while conceptually it "replies back", technically it just sends a new `pong`
@@ -363,7 +362,7 @@ request-response pattern, i.e. it "knows" whom to send back the "reply".
 
 
 Lets move forward.
 Lets move forward.
 
 
-```
+~~~{.cpp}
 using Supervisor = rl::Supervisor<
 using Supervisor = rl::Supervisor<
     rl::SupervisorBase::min_handlers_amount,
     rl::SupervisorBase::min_handlers_amount,
     Pinger,
     Pinger,
@@ -373,13 +372,13 @@ using Storage = rl::traits::MessageStorage<rl::message::ChangeState,
                                            rl::message::ChangeStateAck,
                                            rl::message::ChangeStateAck,
                                            message::Ping,
                                            message::Ping,
                                            message::Pong>;
                                            message::Pong>;
-```
+~~~
 
 
 The standard supervisor is used; it owns `pinger` and `ponger` actors. The `Storage`
 The standard supervisor is used; it owns `pinger` and `ponger` actors. The `Storage`
 allocates enough space for `Ping` and `Pong` messages.
 allocates enough space for `Ping` and `Pong` messages.
 
 
 
 
-```
+~~~{.cpp}
 int main(int, char **) {
 int main(int, char **) {
 
 
   app_hw_init();
   app_hw_init();
@@ -397,19 +396,20 @@ int main(int, char **) {
   sup.process();   // (43)
   sup.process();   // (43)
   return 0;
   return 0;
 }
 }
-```
+~~~
 
 
 The most interesting part is the setup-phase (39-40). `pinger` and `ponger` actors
 The most interesting part is the setup-phase (39-40). `pinger` and `ponger` actors
 should know each others addresses, and the addresses are available only after
 should know each others addresses, and the addresses are available only after
 context binding.
 context binding.
 
 
 When everything is ready, it enters into main loop (43). In the loop it either
 When everything is ready, it enters into main loop (43). In the loop it either
-delivers `rotor-light` messages or waits, until the next event time occurs. It uses
-**busy waiting** by actively polling (querying) timer, whether the next event time
-happend. As usually for busy waiting, it consumes 100% CPU time, which is common
-strategy for embedded/real-time applications.
+delivers [rotor-light](https://notabug.org/basiliscos/cpp-rotor-light) messages
+or waits, until the next event time occurs. It uses **busy waiting** by actively
+polling (querying) timer, whether the next event time happend. As usually for
+busy waiting, it consumes 100% CPU time, which is common strategy for
+embedded/real-time applications.
 
 
-It is possible however to do something else, instead of endless timer polling, i.e.
+It is possible however to do something else, instead of endless timer polling, e.g.
 do CPU sleep (and consume less current and do less CO2 emission). See the
 do CPU sleep (and consume less current and do less CO2 emission). See the
 next section.
 next section.
 
 
@@ -423,12 +423,12 @@ delay the procedure repeats.
 However, the notable difference is in the delay: in the previous example it
 However, the notable difference is in the delay: in the previous example it
 endlessly polls the timer whether the time arrives for the next event, burning
 endlessly polls the timer whether the time arrives for the next event, burning
 CPU cycles, in the current example it does energy-efficient sleeping while
 CPU cycles, in the current example it does energy-efficient sleeping while
-there is noting to do (i.e. no messages) between events.
+there is nothing to do (i.e. no messages) between events.
 
 
 As the main logic is the same, the actor-related code is also the same; only
 As the main logic is the same, the actor-related code is also the same; only
 `main()` function differs. 
 `main()` function differs. 
 
 
-```
+~~~{.cpp}
 int main(int, char **) {
 int main(int, char **) {
   app_hw_init();
   app_hw_init();
 
 
@@ -452,13 +452,12 @@ int main(int, char **) {
     sup.process();                                 // (46)
     sup.process();                                 // (46)
     auto next_event_time = planner.next_event();   // (47)
     auto next_event_time = planner.next_event();   // (47)
     if (next_event_time) {                         // (48)
     if (next_event_time) {                         // (48)
-      perform_sleep(next_event_time);              // (49)
+      Board::sleep(next_event_time);               // (49)
     }
     }
   }
   }
   return 0;
   return 0;
 }
 }
-
-```
+~~~
 
 
 Firstly, the timer poll via recursively sending self `refresh-timer` message should
 Firstly, the timer poll via recursively sending self `refresh-timer` message should
 be disabled (44). Then the infinite loop (45) should be started, as the supervisor
 be disabled (44). Then the infinite loop (45) should be started, as the supervisor
@@ -480,7 +479,7 @@ the powersave mode.
 Then second way is to have a custom supervisor with `on_refhesh_timer` method
 Then second way is to have a custom supervisor with `on_refhesh_timer` method
 overridden, like that:
 overridden, like that:
 
 
-```
+~~~{.cpp}
 struct MySupervisor : rl::Supervisor<3, MyActor1, MyActor2, ...> {
 struct MySupervisor : rl::Supervisor<3, MyActor1, MyActor2, ...> {
 using Parent = rl::Supervisor<3, MyActor1, MyActor2, ...>; 
 using Parent = rl::Supervisor<3, MyActor1, MyActor2, ...>; 
 
 
@@ -490,5 +489,4 @@ void on_refhesh_timer(rl::message::RefreshTime &message) override {
 }
 }
 
 
 };
 };
-
-```
+~~~

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 1
docs/actor-lifetime.drawio


BIN
docs/actor-lifetime.png


+ 0 - 0
docs/extra.css


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor