Zephyr C++ Toolkit
|
Use this class in your objects to create a thread that can wait for events. More...
#include <EventThread.hpp>
Public Types | |
using | MsgQueueItem = std::variant< EventType, std::function< void()> > |
Public Member Functions | |
EventThread (const char *name, k_thread_stack_t *threadStack, size_t threadStackSize, int threadPriority, size_t eventQueueBufferNumItems) | |
~EventThread () | |
void | start () |
void | onExternalEvent (std::function< void(const EventType &)> callback) |
void | sendEvent (const EventType &event) |
TimerManager & | timerManager () |
void | exitEventLoop () |
void | runInLoop (std::function< void()> func) |
Protected Member Functions | |
void | runEventLoop () |
Static Protected Member Functions | |
static void | staticThreadFunction (void *arg1, void *arg2, void *arg3) |
Protected Attributes | |
const char * | m_name = nullptr |
void * | m_msgQueueBuffer = nullptr |
struct k_thread | m_thread |
struct k_msgq | m_threadMsgQueue |
k_thread_stack_t * | m_threadStack |
size_t | m_threadStackSize |
int | m_threadPriority |
TimerManager | m_timerManager |
std::function< void(const EventType &)> | m_externalEventCallback = nullptr |
bool | m_exitEventLoop = false |
Use this class in your objects to create a thread that can wait for events.
This class spawns a new Zephyr thread.
The user is responsible for making sure the thread function returns if you want to destroy this object. This is because the destructor blocks until the thread is complete. The best way to do this is to implement a exit event and send it to the event thread. The event thread returns when it receives the exit event.
Making sure to return from the thread function is only important if you are destroying the object, e.g. in testing.
This class works really well with event driven programming and hierarchical state machines (HSM) like NinjaHSM.
Below is an example of how to use this class.
using zct::EventThread< EventType >::MsgQueueItem = std::variant<EventType, std::function<void()> > |
The type of items that can be sent to the event thread. Can either be an event or a function to run in the context of the event thread.
This is a variant of the event type and a function to run in the context of the event thread.
|
inline |
Create a new event thread.
Dynamically allocates memory for the event queue buffer. At the moment, you have to allocate the thread stack yourself and pass it in. Once Zephyr's dynamic thread support is out of experimental (and working), hopefully we can just pass in the desired stack size.
name | The name of the this event thread. Used for logging purposes. The Zephyr thread name will also be set to this name. |
threadStack | The stack to use for the thread. You can use K_KERNEL_STACK_MEMBER(m_threadStack, THREAD_STACK_SIZE); to declare a stack member in the parent class that encloses this event thread. |
threadStackSize | The size of the stack provided. |
threadPriority | The priority to assign to the thread. |
eventQueueBufferNumItems | The number of items in the event queue. |
|
inline |
Destroy the event thread. This will block until the thread has exited.
If you want this function to return, make sure the event loop exits. The best way to do this is to call exitEventLoop() from a timer callback or external event handler.
|
inline |
Exit the event loop. This will cause runEventLoop() to return. This function must be called from the event thread context (i.e. from a timer callback or from an external event handler).
This will make the event loop return from runEventLoop() as soon as the timer callback or external event handler returns.
Use this in tests to cleanly exit from the event loop and it's corresponding thread.
|
inline |
Set the callback function to be called when external events are received.
The callback is executed in the context of the event thread.
This function should be used to setup the external event callback before start() is called to start the event loop.
callback | The callback function to call when an external event is received. The callback will be passed the received event. |
|
inlineprotected |
Start the event loop. This function never returns and should be called from the thread function that is passed in to the constructor.
This function will:
This should be called from the thread function that is passed in to the constructor, once any initialisation you want done (e.g. setup some timers) has been done.
|
inline |
Run a function in the context of the event thread. This passes the function through the message queue. When the event loop thread receives it, it runs the function.
func | The function to run. This will be run in the context of the event thread. |
|
inline |
Send an event to this event thread. This can be called from any other thread to send an event to this event thread.
event | The event to send. It is copied into the event queue so it's lifetime only needs to be as long as this function call. |
|
inline |
Start the event thread. This creates and starts the Zephyr thread which will begin running the event loop.
This should be called after the constructor and after any setup (like registering timers) has been completed.
|
inlinestaticprotected |
The function needed by pass to Zephyr's thread API
|
inline |
Call to get the timer manager for this event thread. This is useful when you want to create timers and then register them with the event thread.
Typically you would call:
|
protected |
Used to signal from exitEventLoop() to the code in the runEventLoop() function to exit.
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |