-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAsyncTaskable.h
More file actions
141 lines (119 loc) · 5.23 KB
/
Copy pathAsyncTaskable.h
File metadata and controls
141 lines (119 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifndef ASYNCTASKABLE_H
#define ASYNCTASKABLE_H
#include <vector>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_heap_caps.h"
#include "Utility/CareLogger.h"
/**
* @brief Abstract class for components that can run asynchronous tasks.
*
* This class provides methods to start, stop, and delete asynchronous tasks.
* It also provides a method to create member asynchronous tasks.
*/
class AsyncTaskable
{
public:
/**
* @brief Starts all asynchronous tasks.
*/
void startAllAsyncTasks()
{
if (asyncTasks.empty()) {
CareLogger::log("No async tasks to start. Initialized?", CareLogger::ERROR);
return;
}
for (auto& task : asyncTasks)
vTaskResume(task);
CareLogger::log("All async tasks started", CareLogger::DEBUG);
}
/**
* @brief Stop all asynchronous tasks.
*/
void stopAllAsyncTasks()
{
for (auto& task : asyncTasks)
vTaskSuspend(task);
CareLogger::log("All async tasks stopped", CareLogger::DEBUG);
}
/**
* @brief Delete all asynchronous tasks.
*/
void deleteAllAsyncTasks()
{
for (auto& task : asyncTasks)
vTaskDelete(task);
asyncTasks.clear();
CareLogger::log("All async tasks deleted", CareLogger::DEBUG);
}
template<class T>
/**
* @brief Creates an asynchronous task that runs a member function of the given class.
*
* @param instance Pointer to the instance of the class.
* @param memberFunction Pointer to the member function to be executed in the task.
* @param taskName Name of the task.
* @param stackSize Stack size for the task.
* @param priority Priority of the task.
* @param taskHandle Pointer to store the created task handle.
*/
void createMemberAsyncTask(T* instance, void (T::*memberFunction)(), const char* taskName, int stackSize, int priority, TaskHandle_t* taskHandle)
{
if (taskHandle == NULL)
{
CareLogger::log("Task handle is NULL creating task: " + String(taskName)+". CANNOT CREATE!", CareLogger::ERROR);
return;
}
// Create persistent storage for the task data
struct TaskData {
T* instance;
void (T::*memberFunction)();
};
TaskData* taskData = new TaskData{instance, memberFunction};
// Create the task using the generic static wrapper
createAsyncTask(memberTaskWrapper<T>, taskName, stackSize, taskData, priority, taskHandle);
}
virtual void initializeAsyncTasks() = 0;
private:
template<class T>
static void memberTaskWrapper(void* params) {
struct TaskData {
T* instance;
void (T::*memberFunction)();
};
TaskData* data = static_cast<TaskData*>(params);
T* obj = data->instance;
auto func = data->memberFunction;
// Call the member function
(obj->*func)();
// Clean up the task data
delete data;
vTaskDelete(NULL);
}
std::vector<TaskHandle_t> asyncTasks;
void createAsyncTask(void (*taskFunction)(void*), const char* taskName, int stackSize, void* parameters, int priority, TaskHandle_t* taskHandle)
{
CareLogger::log("Creating async task: " + String(taskName) + " with stack: " + String(stackSize), CareLogger::DEBUG);
// Log available memory before task creation
//size_t freeHeap = esp_get_free_heap_size();
//size_t minFreeHeap = esp_get_minimum_free_heap_size();
//CareLogger::log("Memory before task creation - Free: " + String(freeHeap) + ", Min Free: " + String(minFreeHeap), CareLogger::DEBUG);
// Create task and immediately suspend it to prevent race conditions
BaseType_t result = xTaskCreate(taskFunction, taskName, stackSize, parameters, priority, taskHandle);
if (result != pdPASS) {
CareLogger::log("CRITICAL: Failed to create task '" + String(taskName) + "' - Out of memory!", CareLogger::ERROR);
CareLogger::log("Free heap: " + String(esp_get_free_heap_size()) + " bytes", CareLogger::ERROR);
CareLogger::log("Required stack: " + String(stackSize * sizeof(StackType_t)) + " bytes", CareLogger::ERROR);
*taskHandle = NULL;
return;
}
if (*taskHandle == NULL) {
CareLogger::log("ERROR: Task handle is NULL after creation for task: " + String(taskName), CareLogger::ERROR);
return;
}
vTaskSuspend(*taskHandle); // Suspend the task after creation
asyncTasks.push_back(*taskHandle);
CareLogger::log("Async task created and suspended: " + String(taskName), CareLogger::DEBUG);
}
};
#endif // ASYNCTASKABLE_H