Ken Van Hoeylandt 686f7cce83
TactilityCore improvements (#187)
FreeRTOS handles were stored plainly and they were deleted in the destructor of classes.
This meant that if a class were to be copied, the destructor would be called twice on the same handles and lead to double-free.

Seha on Discord suggested to fix this by using `std::unique_ptr` with a custom deletion function.

The changes affect:
- Thread
- Semaphore
- Mutex
- StreamBuffer
- Timer
- MessageQueue
- EventFlag

Thread  changes:
- Removal of the hack with the `Data` struct
- Thread's main body is now just a private static function inside the class.
- The C functions were relocated to static class members

PubSub changes:
- Refactored pubsub into class
- Renamed files to `PubSub` instead of `Pubsub`
- `PubSubSubscription` is now a private inner struct and `PubSub` only exposes `SubscriptionHandle`

Lockable, ScopedLockable, Mutex:
- Added `lock()` method that locks indefinitely
- Remove deprecated `acquire()` and `release()` methods
- Removed `TtWaitForever` in favour of `portMAX_DELAY`
2025-01-25 17:29:11 +01:00

65 lines
1.5 KiB
C++

/**
* @file Dispatcher.h
*
* Dispatcher is a thread-safe code execution queue.
*/
#pragma once
#include "MessageQueue.h"
#include "Mutex.h"
#include "EventFlag.h"
#include <memory>
#include <queue>
namespace tt {
/**
* A thread-safe way to defer code execution.
* Generally, one task would dispatch the execution,
* while the other thread consumes and executes the work.
*/
class Dispatcher {
public:
typedef void (*Function)(std::shared_ptr<void> data);
private:
struct DispatcherMessage {
Function function;
std::shared_ptr<void> context; // Can't use unique_ptr with void, so we use shared_ptr
DispatcherMessage(Function function, std::shared_ptr<void> context) :
function(function),
context(std::move(context))
{}
~DispatcherMessage() = default;
};
Mutex mutex;
std::queue<std::shared_ptr<DispatcherMessage>> queue;
EventFlag eventFlag;
public:
explicit Dispatcher() = default;
~Dispatcher();
/**
* Queue a function to be consumed elsewhere.
* @param[in] function the function to execute elsewhere
* @param[in] context the data to pass onto the function
*/
void dispatch(Function function, std::shared_ptr<void> context);
/**
* Consume a dispatched function (if any)
* @param[in] timeout the ticks to wait for a message
* @return the amount of messages that were consumed
*/
uint32_t consume(TickType_t timeout = portMAX_DELAY);
};
} // namespace