From 2bf8fd1359039831bb52bd32c27aaf9f44293d68 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 25 Apr 2026 12:50:43 +0200 Subject: [PATCH] Converted more documentation pages Modified the site CSS --- docs/Messaging/_index.md | 4 + .../message-broker.md} | 178 ++-- docs/Messaging/message-bus.md | 206 +++++ docs/Messaging/message-packet.md | 155 ++++ docs/Messaging/messages.md | 111 +++ docs/Messaging/shared-message.md | 78 ++ docs/frameworks/_index.md | 4 + .../callback-service.md} | 93 +- docs/frameworks/cooperative-scheduler.md | 211 +++++ .../finite-state-machine.md} | 360 +++++--- docs/{raw => }/frameworks/hfsm.png | Bin .../hierarchical-finite-state-machine.md | 100 +++ docs/frameworks/task.md | 75 ++ docs/patterns/singleton-base.md | 53 ++ .../Singleton.txt => patterns/singleton.md} | 116 ++- .../Visitor.txt => patterns/visitor.md} | 99 ++- docs/raw/frameworks/Cooperative Scheduler.txt | 183 ---- .../Hierarchical Finite State Machine.txt | 98 --- docs/raw/frameworks/Message Bus.txt | 157 ---- docs/raw/frameworks/Messages.txt | 82 -- docs/raw/frameworks/Shared Messages.txt | 38 - docs/raw/frameworks/Task.txt | 41 - docs/raw/frameworks/message_packet.txt | 103 --- docs/raw/patterns/Singleton Base.txt | 41 - .../strings/string.txt => strings/string.md} | 815 +++++++++++++----- docs/strings/string_stream.md | 4 + .../string_view.md} | 315 +++++-- .../to_arithmetic.md} | 270 ++++-- .../to_string.txt => strings/to_string.md} | 77 +- hugo/assets/css/custom.css | 14 +- 30 files changed, 2636 insertions(+), 1445 deletions(-) create mode 100644 docs/Messaging/_index.md rename docs/{raw/frameworks/Message Broker.txt => Messaging/message-broker.md} (52%) create mode 100644 docs/Messaging/message-bus.md create mode 100644 docs/Messaging/message-packet.md create mode 100644 docs/Messaging/messages.md create mode 100644 docs/Messaging/shared-message.md create mode 100644 docs/frameworks/_index.md rename docs/{raw/frameworks/Callback Service.txt => frameworks/callback-service.md} (50%) create mode 100644 docs/frameworks/cooperative-scheduler.md rename docs/{raw/frameworks/Finite State Machine.txt => frameworks/finite-state-machine.md} (51%) rename docs/{raw => }/frameworks/hfsm.png (100%) create mode 100644 docs/frameworks/hierarchical-finite-state-machine.md create mode 100644 docs/frameworks/task.md create mode 100644 docs/patterns/singleton-base.md rename docs/{raw/patterns/Singleton.txt => patterns/singleton.md} (51%) rename docs/{raw/patterns/Visitor.txt => patterns/visitor.md} (65%) delete mode 100644 docs/raw/frameworks/Cooperative Scheduler.txt delete mode 100644 docs/raw/frameworks/Hierarchical Finite State Machine.txt delete mode 100644 docs/raw/frameworks/Message Bus.txt delete mode 100644 docs/raw/frameworks/Messages.txt delete mode 100644 docs/raw/frameworks/Shared Messages.txt delete mode 100644 docs/raw/frameworks/Task.txt delete mode 100644 docs/raw/frameworks/message_packet.txt delete mode 100644 docs/raw/patterns/Singleton Base.txt rename docs/{raw/strings/string.txt => strings/string.md} (56%) rename docs/{raw/strings/string_view.txt => strings/string_view.md} (53%) rename docs/{raw/strings/to_arithmetic.txt => strings/to_arithmetic.md} (60%) rename docs/{raw/strings/to_string.txt => strings/to_string.md} (53%) diff --git a/docs/Messaging/_index.md b/docs/Messaging/_index.md new file mode 100644 index 00000000..6bfb61be --- /dev/null +++ b/docs/Messaging/_index.md @@ -0,0 +1,4 @@ +--- +title: "Messaging" +weight: 100 +--- diff --git a/docs/raw/frameworks/Message Broker.txt b/docs/Messaging/message-broker.md similarity index 52% rename from docs/raw/frameworks/Message Broker.txt rename to docs/Messaging/message-broker.md index f6e9cfd5..f37a89ae 100644 --- a/docs/raw/frameworks/Message Broker.txt +++ b/docs/Messaging/message-broker.md @@ -1,78 +1,146 @@ -Message Broker +--- +title: "message_broker" +--- -A variant of the observer pattern in that message routers and derived types are be able to subscribe to selected sets of messages. The message_broker is similar to the message_bus, but it provides more control over the routing of messages. While the message_bus simply broadcasts every message to all subscribers, the message_broker allows you to specify which subscribers should receive each message. +{{< callout type="info">}} + Header: `message_broker.h` +{{< /callout >}} -Derived from imessage_router -____________________________________________________________________________________________________ -Types +Message Broker +A variant of the observer pattern in that message routers and derived types are be able to subscribe to selected sets of messages. The message_broker is similar to the message_bus, but it provides more control over the routing of messages. While the message_bus simply broadcasts every message to all subscribers, the message_broker allows you to specify which subscribers should receive each message. + +Derived from `imessage_router`. + +## Types + +```cpp message_id_span_t etl::span -____________________________________________________________________________________________________ -subscription -A nested class of etl::message_broker -The base for broker subscription information. -Derive from this to define your subscription class. -See Example. -____________________________________________________________________________________________________ -subscription(etl::imessage_router& router) -Constructor. -____________________________________________________________________________________________________ -virtual message_id_span_t message_id_list() const = 0; -Override this to return a span of message ids. -____________________________________________________________________________________________________ -message_broker +``` +## subscription +A nested class of `etl::message_broker`. +The base for broker subscription information. +Derive from this to define your subscription class. +See Example. + +--- + +```cpp +subscription(etl::imessage_router& router) +``` +Constructor. + +--- + +```cpp +virtual message_id_span_t message_id_list() const = 0; +``` +Override this to return a span of message ids. + +## message_broker + +```cpp message_broker() -The broker is constructed with an id of etl::imessage_router::MESSAGE_BROKER. -____________________________________________________________________________________________________ +``` +The broker is constructed with an id of `etl::imessage_router::MESSAGE_BROKER`. + +--- + +```cpp message_broker(etl::imessage_router& successor) -The broker is constructed with an id of etl::imessage_router::MESSAGE_BROKER. +``` +The broker is constructed with an id of `etl::imessage_router::MESSAGE_BROKER`. Sets the successor. -____________________________________________________________________________________________________ + +--- + +```cpp message_broker(etl::message_router_id_t id) +``` The broker is constructed with the specified id. -____________________________________________________________________________________________________ + +--- + +```cpp message_broker(etl::message_router_id_t id, etl::imessage_router& successor) -The broker is constructed with the specified id. +``` +The broker is constructed with the specified id. Sets the successor. -____________________________________________________________________________________________________ + +--- + +```cpp void subscribe(etl::imessage_router& router) -Subscribes an etl::imessage_router derived class to the broker. -A subscription object must have a lifetime of at least the same as the broker. +``` +Subscribes an `etl::imessage_router` derived class to the broker. +A subscription object must have a lifetime of at least the same as the broker. A subscription cannot be shared with another broker. -____________________________________________________________________________________________________ + +--- + +```cpp void unsubscribe(etl::imessage_router& router) -Unsubscribes the specified etl::imessage_router derived class from the bus. +``` +Unsubscribes the specified `etl::imessage_router` derived class from the bus. Does not unsubscribe from nested buses. -____________________________________________________________________________________________________ + +--- + +```cpp void receive(const etl::imessage& message) void receive(etl::shared_message message) -Receives a message and distributes it to all subscribers that have registered to receive the message type. -Forwards the message to any successor. +``` +Receives a message and distributes it to all subscribers that have registered to receive the message type. +Forwards the message to any successor. -Override this in a derived class if you wish to capture messages sent to the broker. +Override this in a derived class if you wish to capture messages sent to the broker. Call the base receive function from here to allow normal operation to continue. -____________________________________________________________________________________________________ -bool accepts(etl::message_id_t id) const -Always returns true. -____________________________________________________________________________________________________ -void clear() -Clears the broker of all subscribers. -____________________________________________________________________________________________________ -ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE -Always returns false. -____________________________________________________________________________________________________ -bool is_producer() const ETL_OVERRIDE -Always returns true. -____________________________________________________________________________________________________ -bool is_consumer() const ETL_OVERRIDE -Always returns true. -____________________________________________________________________________________________________ -bool empty() const -Returns true is the are are no subscribers. -____________________________________________________________________________________________________ -Example +--- + +```cpp +bool accepts(etl::message_id_t id) const +``` +Always returns `true`. + +--- + +```cpp +void clear() +``` +Clears the broker of all subscribers. + +--- + +```cpp +ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE +``` +Always returns `false`. + +--- + +```cpp +bool is_producer() const ETL_OVERRIDE +``` +Always returns `true`. + +--- + +```cpp +bool is_consumer() const ETL_OVERRIDE +``` +Always returns `true`. + +--- + +```cpp +bool empty() const +``` +Returns `true` is the are are no subscribers. + +## Example +```cpp // Some router ids. enum { @@ -145,4 +213,4 @@ broker.receive(message1); // Received by router1 broker.receive(message2); // Received by router1 and router2 broker.receive(message3); // Received by router2 broker.receive(message4); // Received by router2 as a Message3 - +``` diff --git a/docs/Messaging/message-bus.md b/docs/Messaging/message-bus.md new file mode 100644 index 00000000..222f665a --- /dev/null +++ b/docs/Messaging/message-bus.md @@ -0,0 +1,206 @@ +--- +title: "message_bus" +--- + +{{< callout type="info">}} + Header: `message_broker.h` + Since: `20.33.0` +{{< /callout >}} + +Message Bus + +This page documents version `20.0.0` and above. + +A variant of the observer pattern in that message routers and derived types are be able to subscribe to messages on a bus. The messages can be either broadcast, to be automatically picked up by any router that has a handler, or addressed to a particular router or router id. Message buses may be nested by setting a successor. + +## imessage_bus +Derived from imessage_router. + +The base for all message buses. +Inherits publicly from `etl::imessage_router`. +Message buses are therefore also a type of router. +Objects of type `etl::imessage_bus` cannot be directly constructed. + +## Member functions + +```cpp +bool subscribe(etl::imessage_router& router) +``` +Subscribes an `etl::imessage_router` derived class to the bus. +Returns `true` on success. + +--- + +```cpp +void unsubscribe(etl::imessage_router& router) +``` +Unsubscribes the specified `etl::imessage_router` derived class from the bus. +Does not unsubscribe from nested buses. + +--- + +```cpp +void unsubscribe(etl::message_router_id_t id) +``` +Unsubscribes routers with the specified id from the bus. +Does not unsubscribe from nested buses. + +`etl::imessage::MESSAGE_BUS` will unsubscribe all message buses. +`etl::imessage::ALL_MESSAGE_ROUTERS` will unsubscribe all routers and buses. Equivalent to calling `clear()`. + +--- + +```cpp +void receive(const etl::imessage& message) +void receive(etl::shared_message message) +``` +Receives a message and distributes it to all subscribers. +Forwards the message to any successor. + +The routers are called first, in order of ascending router id. +Routers with the duplicate ids will be called in subscribe order. +Any nested message buses are called in subscribe order. + +--- + +```cpp +void receive(etl::message_router_id_t destination_router_id, + const etl::imessage& message); +void receive(etl::message_router_id_t destination_router_id, + etl::shared_message message) +``` +Receives a message and distributes it to all subscribers that have the specified router id. +Forwards the message to any successor. + +Routers with the duplicate ids will be called in subscribe order. +Any nested message buses are called in subscribe order. + +Override this in a derived class if you wish to capture messages sent to the bus. +Call the base receive function from here to allow normal operation to continue. + +--- + +```cpp +bool accepts(etl::message_id_t id) const +``` +Always returns `true`. + +--- + +```cpp +size_t size() const +``` +Returns the number of subscribers. + +--- + +```cpp +void clear() +``` +Clears the bus of all subscribers. + +Message buses inherit all of the public functions of `etl::imessage_router`. + +## Errors + +```cpp +message_bus_exception +``` +Base error class for `etl::message_bus`. Inherits from `etl::exception`. + +--- + +```cpp +message_bus_too_many_subscribers +``` +Emitted when the number of subscribers exceeds the capacity. Inherits from `etl::message_bus_exception`. + +## message_bus +Derived from `imessage_bus`. + +```cpp +template +class message_bus +``` +`MAX_ROUTERS` The maximum number of routers that can be subscribed. + +## Member functions + +```cpp +message_bus() +``` +Constructs a message bus. +Message buses always have a router id of `etl::imessage::MESSAGE_BUS`. + +```cpp +message_bus(etl::imessage_router& successor) +``` +Constructs a message bus and sets the successor. +Message buses always have a router id of `etl::imessage::MESSAGE_BUS`. + +## Example +```cpp +// Some router ids. +enum +{ + ROUTER_ID_1, + ROUTER_ID_2, + ROUTER_ID_3 +}; + +// Instances of messages. +MessageA messageA; + +// Instances of message routers. +RouterA routerA(ROUTER_ID_1); +RouterB routerB(ROUTER_ID_1); +RouterC routerC(ROUTER_ID_2); +RouterD routerD(ROUTER_ID_3); +RouterE routerE(ROUTER_ID_1); + +// Instances of message buses. +etl::message_bus<4> bus1; +etl::message_bus<2> bus2; +etl::message_bus<1> bus3; + +// Subscribe bus2 & bus3 to bus1. +bus1.subscribe(bus3); +bus1.subscribe(bus2); + +// Subscribe routerB & routerA to bus1. +bus1.subscribe(routerB); +bus1.subscribe(routerA); + +// Subscribe routerD & routerC to bus2. +bus2.subscribe(routerD); +bus2.subscribe(routerC); + +// Subscribe routerE to bus3. +bus3.subscibe(routerE); + +// Assume all routers accept the same messages. + +// Broadcast messageA to everyone. +bus1.receive(messageA); + +// The call order will be... +// routerB +// routerA +// routerE +// routerC +// routerD + +// Address messageA to routers with id ROUTER_ID_1. +bus1.receive(ROUTER_ID_1, messageA); + +// The call order will be... +// routerB +// routerA +// routerE + +// Address messageA to routers with id ROUTER_ID_3. +bus1.receive(ROUTER_ID_3, messageA); +``` +// The call order will be... +// routerD +``` diff --git a/docs/Messaging/message-packet.md b/docs/Messaging/message-packet.md new file mode 100644 index 00000000..5854bfab --- /dev/null +++ b/docs/Messaging/message-packet.md @@ -0,0 +1,155 @@ +--- +title: "message_packet" +--- + +{{< callout type="info">}} + Header: `message_packet.h` +{{< /callout >}} + +A container for more than one type of message. +The messages must have been derived from `etl::imessage`. + +The messages types that the packet may contain are listed as template parameters. +e.g. `etl::message_packet` + +From `20.40.0` message types are not required to have a virtual destructor. + +--- + +```cpp +message_packet() +``` +Default constructs a message packet. +`is_valid()` returns `false`. + +--- + +```cpp +explicit message_packet(const etl::imessage&) +``` +Constructs a message packet from an `etl::imessage` reference. +Asserts an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list. + +--- + +```cpp +explicit message_packet(etl::imessage&&) C++11 +``` +Move constructs a message packet from an `etl::imessage` rvalue reference. +Emits an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list. + +--- + +```cpp +template +explicit message_packet(const TMessage&) +``` +Constructs a message packet from a `TMessage` reference. +Emits a compile time static assert if the parameter is not one listed in the template parameter list. +Since: `20.22.0` + +--- + +```cpp +template +explicit message_packet(TMessage&&) +``` +Move constructs a message packet from a `TMessage` rvalue reference. +Emits a compile time static assert if the parameter is not one listed in the template parameter list. +Since: `20.22.0` + +--- + +```cpp +message_packet(const message_packet&) +``` +Constructs a message packet from an `message_packet` reference. +Emits an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list. + +--- + +```cpp +message_packet(message_packet&&) +``` +Move constructs a message packet from an `message_packet` rvalue reference. +Emits an `etl::unhandled_message_exception` if the parameter is not one listed in the template parameter list. + +--- + +```cpp +message_packet& operator =(const message_packet&) +``` +Assigns a message packet from an `message_packet` reference. +Emits an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list. + +--- + +```cpp +message_packet& operator =(message_packet&&) +``` +Move assigns a message packet from an `message_packet` rvalue reference. +Emits an `etl::unhandled_message_exception` error if the parameter is not one listed in the template parameter list. + +--- + +```cpp +etl::imessage& get() +const etl::imessage& get() const +``` +Returns a reference to an `etl::imessage`. + +--- + +```cpp +bool is_valid() const +``` +Returns `true` if the packet contains a valid message, otherwise `false`. + +--- + +## Constants + +`SIZE` The size of the largest message. +`ALIGNMENT` The largest message alignment. + +--- + +## Example +```cpp +enum +{ + MESSAGE1, + MESSAGE2, + MESSAGE3 +}; + +struct Message1 : public etl::message +{ +}; + +struct Message2 : public etl::message +{ +}; + +struct Message3 : public etl::message +{ +}; + +using Packet = etl::message_packet + +Message1 message1; +Message2 message2; +Message3 message3; + +Packet packet1(message1); +Packet packet2(message2); +Packet packet3(message3); // Runtime time error! Packet does not support Message3 type. + +etl::imessage& m1 = message1; +Packet packet4(m1); // Construct from an etl::imessage reference. + +etl::imessage& m3 = message3; +Packet packet4(m3); // Asserts etl::unhandled_message_exception! Packet does not support Message3 type. + +etl::imessage& m = packet2.get(); // Get a reference to an etl::imessage from the packet. +``` diff --git a/docs/Messaging/messages.md b/docs/Messaging/messages.md new file mode 100644 index 00000000..2a49e91e --- /dev/null +++ b/docs/Messaging/messages.md @@ -0,0 +1,111 @@ +--- +title: "Messages" +--- + +{{< callout type="info">}} + Header: `message.h` +{{< /callout >}} + +Message types used for many of the framework classes. + +--- + +```cpp +etl::message_id_t +``` +The type used for message ids. +By default can hold a value between 0 and 255. +If `ETL_MESSAGE_ID_TYPE` is defined then this type will be used instead. + +--- + +```cpp +etl::message_router_id_t +``` +The type used for message router ids. +Can hold a value between 0 and 255. + +--- + +The message classes are the common communication method across all of the message capable frameworks. +They are identified by a unique id number that specialises the base class. + +## imessage + +The base class for messages. +It is this class that is passed around, usually by const reference. +The class is abstract. + +--- + +```cpp +etl::message_id_t get_message_id() const ETL_NOEXCEPT = 0; +``` +Returns the id of the message. + +--- + +## message + +```cpp +message +``` +Requires an integral id as the template parameter. +Inherits from `TParent`, which defaults to `etl::imessage`. +`TParent` allows additional base interfaces or functionality to be included. +static asserts if `TParent` is not a base of `etl::imessage`. + +--- + +```cpp +ID +``` +The id of the message as an enum. +Can be accessed by `etl::message` instances. + +--- + +```cpp +TParent +``` +The class that it inherits from. It must ultimately derive from `etl::imessage`. +The default is `etl::imessage`. + +--- + +## Example + +```cpp +enum +{ + START, + STOP, + SET_SPEED +}; + +struct MyInterface : public etl::imessage +{ + virtual void DoStuff() = 0; +}; + +// Start implements MyIterface +struct Start : public etl::message +{ + void DoStuff() override + { + // Do stuff here. + } +}; + +struct Stop : public etl::message +{ + bool isEmergencyStop; +}; + +struct SetSpeed : public etl::message +{ + uint32_t speed; +}; + +void Receive(const etl::imessage& msg); +``` diff --git a/docs/Messaging/shared-message.md b/docs/Messaging/shared-message.md new file mode 100644 index 00000000..8e190308 --- /dev/null +++ b/docs/Messaging/shared-message.md @@ -0,0 +1,78 @@ +--- +title: "shared_message" +--- + +{{< callout type="info">}} + Header: `shared_message.h` +{{< /callout >}} + +Shared Messages + +The type used to encapsulate reference counted messages. +Shared messages are usually passed by value. + +See the Shared Message Tutorial + +--- + +```cpp +template +shared_message(TPool& owner, const TMessage& message) +``` +Static asserts if `TPool` is not derived from `etl::ireference_counted_message_pool` +Static asserts if `TMessage` not derived from `etl::imessage`. + +Requires that `TPool` implements the following member function to allocate from the pool. + +```cpp +template +etl::ireference_counted_message* allocate(const TMessage& message) +``` +--- + +```cpp +explicit shared_message(etl::ireference_coutnted_message& message) +``` +Construct from a reference counted message. + +--- + +```cpp +shared_message(const etl::shared_message& other) +``` +Copy constructor. + +--- + +```cpp +shared_message& operator =(const etl::shared_message& other) +``` +Assignment operator. + +--- + +```cpp +~shared_message() +``` +Destructor. + +--- + +```cpp +ETL_NODISCARD etl::imessage& get_message() +``` +Gets a reference to the contained message. + +--- + +```cpp +ETL_NODISCARD const etl::imessage& get_message() const +``` +Gets a const reference to the contained message. + +--- + +```cpp +ETL_NODISCARD uint32_t get_reference_count() const +``` +Gets the current reference count for this shared message. diff --git a/docs/frameworks/_index.md b/docs/frameworks/_index.md new file mode 100644 index 00000000..5a85aae8 --- /dev/null +++ b/docs/frameworks/_index.md @@ -0,0 +1,4 @@ +--- +title: "Frameworks" +weight: 100 +--- diff --git a/docs/raw/frameworks/Callback Service.txt b/docs/frameworks/callback-service.md similarity index 50% rename from docs/raw/frameworks/Callback Service.txt rename to docs/frameworks/callback-service.md index 5cc8868b..d06e04ad 100644 --- a/docs/raw/frameworks/Callback Service.txt +++ b/docs/frameworks/callback-service.md @@ -1,57 +1,80 @@ -Callback Service -This template class allows easier integration of 'C' style events (such as interrupt vectors) and C++ handlers. -It can allow abstraction between low level events such as interrupts and their application dependent handlers. -The handlers may be any combination of global, static or member functions. -It utilises the templated function wrapper. See here. +--- +title: "callback_service" +--- -The callbacks are identified by an id. The values of the ids must range from zero or a specified offset, up to the maximum number of specified callbacks. Calling an unused callback id will either do nothing or, if the user has specified a handler, call this with the id of the callback. +{{< callout type="info">}} + Header: `callback_service.h` +{{< /callout >}} -There are functions that use both runtime and compile time checks of the callback id. -Compile time is preferable. -____________________________________________________________________________________________________ -Member functions +This template class allows easier integration of 'C' style events (such as interrupt vectors) and C++ handlers. +It can allow abstraction between low level events such as interrupts and their application dependent handlers. +The handlers may be any combination of global, static or member functions. +It utilises the templated function wrapper. +The callbacks are identified by an id. The values of the ids must range from zero or a specified offset, up to the maximum number of specified callbacks. Calling an unused callback id will either do nothing or, if the user has specified a handler, call this with the id of the callback. + +There are functions that use both runtime and compile time checks of the callback id. +Compile time is preferable. + +## Member functions + +```cpp template etl::callback_service +``` +`RANGE` The id range of the callbacks. +`OFFSET` The starting id for the range. -RANGE The id range of the callbacks. -OFFSET The starting id for the range. -____________________________________________________________________________________________________ +It can allow abstraction between low level events such as interrupts and their application dependent handlers. + +```cpp callback_service() - -Sets all of the callbacks to route to the unhandled callback. +``` +Sets all of the callbacks to route to the unhandled callback. Sets the unhandled callback to default (do nothing). -____________________________________________________________________________________________________ + +--- + +```cpp template void register_callback(etl::ifunction& callback) - -Registers callback with the id specified in the template parameter. +``` +Registers callback with the id specified in the template parameter. A compile time error will occur if the id is out of range. -____________________________________________________________________________________________________ + +--- + +```cpp void register_callback(size_t id, etl::ifunction& callback) - -Registers callback with the id specified in the template parameter. +``` +Registers callback with the id specified in the template parameter. The registration will be ignored if the id is out of range. -____________________________________________________________________________________________________ -void register_unhandled_callback(etl::ifunction& callback) +--- + +```cpp +void register_unhandled_callback(etl::ifunction& callback) +``` Registers the callback to be used for unhandled ids. -____________________________________________________________________________________________________ + +--- + +```cpp template void callback() - -Calls the callback associated with the id. -Calls the unhandled callback if the id has not been registered. +``` +Calls the callback associated with the id. +Calls the unhandled callback if the id has not been registered. A compile time error will occur if the id is out of range. -____________________________________________________________________________________________________ + +--- + +```cpp void callback(const size_t id) - -Calls the callback associated with the id. +``` +Calls the callback associated with the id. Calls the unhandled callback if the id has not been registered or if is out of range. -____________________________________________________________________________________________________ -Example -Tutorial - -See the example project in etl\examples\FunctionInterruptSimulation +## Example +See the example project in `examples\FunctionInterruptSimulation`. diff --git a/docs/frameworks/cooperative-scheduler.md b/docs/frameworks/cooperative-scheduler.md new file mode 100644 index 00000000..d6bdeb90 --- /dev/null +++ b/docs/frameworks/cooperative-scheduler.md @@ -0,0 +1,211 @@ +--- +title: "scheduler" +--- + +{{< callout type="info">}} + Header: `scheduler.h` +{{< /callout >}} + +A lightweight cooperative multi-tasking scheduler. +Can be used stand-alone or in conjunction with a messaging system such as the ETL's message router or FSM as the back-end handler. For use when a complex OS or RTOS is overkill. + +Calls an 'idle' callback whenever the scheduler returns `true`. +Calls a 'watchdog' callback whenever the scheduler returns. + +The scheduler makes use of `etl::task`. + +## Scheduling Policies +A number of built-in scheduling policies are available. +Note: The tasks are stored in decreasing priority id order. i.e. Higher id = higher priority. + +### Sequential Single +```cpp +etl::scheduler_policy_sequential_single +``` +A sequential algorithm that calls a task if it has work to do , starting from the highest priority task. +On return, it moves to the next task in the list. At the end of the list it returns the idle status. +If no tasks with work were found then the idle status is set to `true`. + +### Sequential Multiple +```cpp +etl::scheduler_policy_sequential_multiple +``` +A sequential algorithm that calls a task if it has work to do , starting from the highest priority task. +On return, it calls the task again if it still has work, otherwise it moves to the next task in the list. +At the end of the list it returns the idle status. +If no tasks with work were found then the idle status is set to `true`. + +### Highest Priority +```cpp +etl::scheduler_policy_highest_priority +``` +An algorithm that calls the highest priority task that has work to do. +Returns the idle status. +If no tasks with work were found then the idle status is set to `true`. + + +### Most Work +```cpp +etl::scheduler_policy_most_work +``` +An algorithm that calls the task that has the most work to do, starting from the highest priority task. +Returns the idle status. +If no tasks with work were found then the idle status is set to `true`. + +### Custom Scheduler +Creating a custom scheduler policy is simple. +Just create a structure with the following signature and add your own scheduling algorithm. +To get 'idle' callbacks then the policy must regularly return `true`. +To get 'watchdog' callbacks then the policy must regularly return. +```cpp +struct scheduler_policy_custom +{ + bool schedule_tasks(etl::ivector& task_list) + { + bool idle = true; + + //************************************** + // Add your scheduling policy here. + // Set 'idle' to false if any tasks were run. + //************************************** + + return idle; + } +}; +``` + +## ischeduler +Can be used as a reference to all scheduler instances. +```cpp +ischeduler() +``` +Constructor + +```cpp +void set_idle_callback(etl::ifunction& callback) +``` +Sets the function to be called when idle. + +--- + +```cpp +void set_watchdog_callback(etl::ifunction& callback) +``` +Sets the function to be called to reset the watchdog. + +--- + +```cpp +void set_scheduler_running(bool scheduler_running) +``` +Sets the running state of the scheduler. + +--- + +```cpp +bool scheduler_is_running() const; +``` +Gets the running state of the scheduler. + +--- + +```cpp +void exit_scheduler() +``` +Instructs the scheduler to exit after the next idle call. + +--- + +```cpp +void add_task(etl::task& task) +``` +Adds a task to the task list. +The task list is in priority order where higher id = higher priority. Tasks with duplicate ids are in insert order. +Emits an `etl::scheduler_too_many_tasks_exception` if the task list is full. + +--- + +```cpp +template +void add_task_list(etl::task** p_tasks, TSize size); +``` +Emits an `etl::scheduler_too_many_tasks_exception` if the task list is full. +Emits an `etl::scheduler_null_task_exception` if any of the task pointers is null. + +--- + +```cpp +virtual void start() +``` +Starts the scheduler. + +## scheduler +Inherits from `etl::ischeduler`. + +```cpp +template +class scheduler +``` +`TSchedulerPolicy` The policy to use schedule tasks. +`MAX_TASKS` The maximum number of tasks to schedule. + +--- + +```cpp +scheduler() +``` +Constructor. + +--- + +```cpp +void start() +``` +Starts the scheduler. +Emits an `etl::scheduler_no_tasks_exception` if there are no tasks in the list. + +## Errors + +```cpp +scheduler_exception +``` +Inherits from `etl::exception` + +--- + +```cpp +scheduler_no_tasks_exception +``` +Inherits from `etl::scheduler_exception` + +--- + +```cpp +scheduler_null_task_exception +``` +Inherits from `etl::scheduler_exception` + +## Overview of use +As a basic example, you will have to define the following... + +**Tasks** +For each of your tasks, derive a class from etl::task and overide the two virtual functions uint32_t task_request_work() const and void task_process_work(). task_request_work returns a value that informs the scheduler that this task has work to process. The return value should be non-zero if the task has work. This meaning of this is user defined, it could be the number of messages in the task's queue, or just a 0 = no work, 1 = have work. task_process_work allows the task to process any work that it has. How much work it processes on each call is user defined; often it will be one 'unit' of work and letting the policy determine which task gets the next opportunity to process more. + +**Task list** +An array of pointers to the tasks. Passed to the scheduler with `add_task_list`. +Use add_task to add additional tasks. + +**The scheduler** +An instance of `etl::scheduler` with the required scheduling policy. +Initialise the task list by calling add_task_list. + +**Callbacks** +If you wish to get callbacks for 'idle' or 'watchdog' then define callback functions and call set_idle_callback and set_watchdog_callback to tell the scheduler. +The callbacks may be global, static or member function, wrapped in an etl::function. + +**Starting the scheduler** +The scheduler is started by calling `start()`. + +## Example + +An example of the scheduler can be found in the repository in `examples/Scheduler`. diff --git a/docs/raw/frameworks/Finite State Machine.txt b/docs/frameworks/finite-state-machine.md similarity index 51% rename from docs/raw/frameworks/Finite State Machine.txt rename to docs/frameworks/finite-state-machine.md index cf489c14..70d3706a 100644 --- a/docs/raw/frameworks/Finite State Machine.txt +++ b/docs/frameworks/finite-state-machine.md @@ -1,15 +1,21 @@ -Finite State Machine +--- +title: "Finite State Machine" +--- -This page documents version 20.0.0 and above. -For version 19.x.x or earlier see this page. +{{< callout type="info">}} + Header: `fsm.h` +{{< /callout >}} -A finite state machine driven by the reception of events (messages) . The incoming messages will be automatically routed to specific handlers based on the message list defined in the template parameters. Optional on_entry and on_exit handlers are available. +This page documents version `20.0.0` and above. -This FSM is slightly more involved to set up than the traditional simple table driven method, but provides great flexibility in implementation. It may also be faster due to the fact that all messages are routed through a direct switch/case/call method rather than scanning a lookup table and calling indirectly through function pointers. +A finite state machine driven by the reception of events (messages) . The incoming messages will be automatically routed to specific handlers based on the message list defined in the template parameters. Optional on_entry and on_exit handlers are available. -The on_event functions are not virtual. The template class uses CRTP to directly call the derived class's functions. +This FSM is slightly more involved to set up than the traditional simple table driven method, but provides great flexibility in implementation. It may also be faster due to the fact that all messages are routed with either O(1) or O(N) rather than scanning a lookup table and calling indirectly through function pointers. -Defines the following classes:- +The `on_event` functions are not virtual. The template class uses [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) to directly call the derived class's functions. + +**Defines the following classes** +```cpp etl::ifsm_state etl::fsm_state <