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`
This commit is contained in:
Ken Van Hoeylandt
2025-01-25 17:29:11 +01:00
committed by GitHub
parent c2edbad0fb
commit 686f7cce83
60 changed files with 711 additions and 831 deletions
+57 -77
View File
@@ -1,11 +1,9 @@
#pragma once
#include "CoreDefines.h"
#include "CoreTypes.h"
#include <cstddef>
#include <cstdint>
#include <string>
#include <memory>
#include "RtosCompatTask.h"
@@ -14,6 +12,7 @@ namespace tt {
typedef TaskHandle_t ThreadId;
class Thread {
public:
enum class State{
@@ -34,6 +33,7 @@ public:
Critical = 7U
};
/** ThreadCallback Your callback to run in new thread
* @warning never use osThreadExit in Thread
*/
@@ -51,22 +51,27 @@ public:
*/
typedef void (*StateCallback)(State state, void* context);
typedef struct {
Thread* thread;
TaskHandle_t taskHandle;
State state;
Callback callback;
void* callbackContext;
int32_t callbackResult;
StateCallback stateCallback;
void* stateCallbackContext;
std::string name;
Priority priority;
configSTACK_DEPTH_TYPE stackSize;
portBASE_TYPE affinity;
} Data;
private:
Thread();
static void mainBody(void* context);
TaskHandle_t taskHandle = nullptr;
State state = State::Stopped;
Callback callback = nullptr;
void* callbackContext = nullptr;
int32_t callbackResult = 0;
StateCallback stateCallback = nullptr;
void* stateCallbackContext = nullptr;
std::string name = {};
Priority priority = Priority::Normal;
configSTACK_DEPTH_TYPE stackSize = 0;
portBASE_TYPE affinity = -1;
void setState(Thread::State state);
public:
Thread() = default;
/** Allocate Thread, shortcut version
* @param[in] name the name of the thread
@@ -76,7 +81,7 @@ public:
* @param[in] affinity Which CPU core to pin this task to, -1 means unpinned (only works on ESP32)
*/
Thread(
const std::string& name,
std::string name,
configSTACK_DEPTH_TYPE stackSize,
Callback callback,
_Nullable void* callbackContext,
@@ -88,7 +93,7 @@ public:
/** Set Thread name
* @param[in] name string
*/
void setName(const std::string& name);
void setName(std::string name);
/** Set Thread stack size
* @param[in] stackSize stack size in bytes
@@ -140,9 +145,39 @@ public:
*/
int32_t getReturnCode() const;
private:
/** Suspend thread
* @param[in] threadId thread id
*/
static void suspend(ThreadId threadId);
Data data;
/** Resume thread
* @param[in] threadId thread id
*/
static void resume(ThreadId threadId);
/** Get thread suspended state
* @param[in] threadId thread id
* @return true if thread is suspended
*/
static bool isSuspended(ThreadId threadId);
/**
* @brief Get thread stack watermark
* @param[in] threadId
* @return uint32_t
*/
static uint32_t getStackSpace(ThreadId threadId);
/** @return pointer to Thread instance or nullptr if this thread doesn't belong to Tactility */
static Thread* getCurrent();
static uint32_t setFlags(ThreadId threadId, uint32_t flags);
static uint32_t clearFlags(uint32_t flags);
static uint32_t getFlags();
static uint32_t awaitFlags(uint32_t flags, uint32_t options, uint32_t timeout);
};
#define THREAD_PRIORITY_APP Thread::PriorityNormal
@@ -150,59 +185,4 @@ private:
#define THREAD_PRIORITY_RENDER Thread::Priority::Higher
#define THREAD_PRIORITY_ISR Thread::Priority::Critical
/** Set current thread priority
* @param[in] priority ThreadPriority value
*/
void thread_set_current_priority(Thread::Priority priority);
/** @return ThreadPriority value */
Thread::Priority thread_get_current_priority();
/** @return FreeRTOS ThreadId or NULL */
ThreadId thread_get_current_id();
/** @return pointer to Thread instance or NULL if this thread doesn't belongs to Tactility */
Thread* thread_get_current();
/** Return control to scheduler */
void thread_yield();
uint32_t thread_flags_set(ThreadId thread_id, uint32_t flags);
uint32_t thread_flags_clear(uint32_t flags);
uint32_t thread_flags_get();
uint32_t thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeout);
/**
* @brief Get thread name
* @param[in] threadId
* @return const char* name or NULL
*/
const char* thread_get_name(ThreadId threadId);
/**
* @brief Get thread stack watermark
* @param[in] threadId
* @return uint32_t
*/
uint32_t thread_get_stack_space(ThreadId threadId);
/** Suspend thread
* @param[in] threadId thread id
*/
void thread_suspend(ThreadId threadId);
/** Resume thread
* @param[in] threadId thread id
*/
void thread_resume(ThreadId threadId);
/** Get thread suspended state
* @param[in] threadId thread id
* @return true if thread is suspended
*/
bool thread_is_suspended(ThreadId threadId);
} // namespace