ソースを参照

v4.0.1 - bug fixes

Anatoli Arkhipenko 3 ヶ月 前
コミット
3e05849d6b

+ 2 - 0
.github/workflows/main.yml

@@ -67,6 +67,8 @@ jobs:
           - "Scheduler_example25_SCHEDULER_CHAIN"
           - "Scheduler_example26_SCHEDULING_OPTIONS"
           - "Scheduler_example28_Tickless"
+          - "Scheduler_example29_NonArduino"
+          - "Scheduler_example30_TASK_THREAD_SAFE"
     # This is the platform GitHub will use to run our workflow,
     # I picked ubuntu.
     runs-on: ubuntu-latest

+ 1 - 1
README.md

@@ -1,6 +1,6 @@
 # Task Scheduler
 ### Cooperative multitasking for Arduino, ESPx, STM32 and other microcontrollers
-#### Version 4.0.0: 2025-09-21 [Latest updates](https://github.com/arkhipenko/TaskScheduler/wiki/Latest-Updates)
+#### Version 4.0.1: 2025-10-07 [Latest updates](https://github.com/arkhipenko/TaskScheduler/wiki/Latest-Updates)
 
 [![arduino-library-badge](https://www.ardu-badge.com/badge/TaskScheduler.svg?)](https://www.ardu-badge.com/TaskScheduler)
 

+ 0 - 10
examples/Scheduler_example27_PlatformIO/.vscode/extensions.json

@@ -1,10 +0,0 @@
-{
-    // See http://go.microsoft.com/fwlink/?LinkId=827846
-    // for the documentation about the extensions.json format
-    "recommendations": [
-        "platformio.platformio-ide"
-    ],
-    "unwantedRecommendations": [
-        "ms-vscode.cpptools-extension-pack"
-    ]
-}

+ 0 - 10
examples/Scheduler_example29_NonArduino/.vscode/extensions.json

@@ -1,10 +0,0 @@
-{
-    // See http://go.microsoft.com/fwlink/?LinkId=827846
-    // for the documentation about the extensions.json format
-    "recommendations": [
-        "platformio.platformio-ide"
-    ],
-    "unwantedRecommendations": [
-        "ms-vscode.cpptools-extension-pack"
-    ]
-}

+ 5 - 0
examples/Scheduler_example30_THREAD_SAFE/.gitignore

@@ -0,0 +1,5 @@
+.pio
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
+.vscode/ipch

+ 232 - 0
examples/Scheduler_example30_THREAD_SAFE/README.md

@@ -0,0 +1,232 @@
+# Example 30: _TASK_THREAD_SAFE - Multi-threaded TaskScheduler
+
+## Overview
+
+This example demonstrates the use of the `_TASK_THREAD_SAFE` compile option for safe multi-threaded operation with TaskScheduler on FreeRTOS-based platforms (ESP32, ESP8266, STM32, etc.).
+
+## What it Demonstrates
+
+### 1. Thread-Safe Request Queue
+- Implementation of required `_task_enqueue_request()` and `_task_dequeue_request()` functions
+- FreeRTOS queue for handling task control requests from multiple threads
+- Automatic handling of ISR vs. normal task context
+
+### 2. ISR-Safe Operations
+- Button interrupt triggering StatusRequest signals
+- Hardware timer ISR changing task parameters
+- Proper use of `requestAction()` from interrupt context
+
+### 3. Multi-Thread Task Control
+- FreeRTOS worker thread adjusting task parameters
+- Safe task manipulation from non-scheduler threads
+- Queue-based communication between threads
+
+### 4. StatusRequest Integration
+- Task waiting on StatusRequest completion
+- Signaling from ISR context
+- Automatic task activation on event
+
+## Hardware Requirements
+
+- **ESP32** development board (recommended)
+- Built-in LED (LED_BUILTIN)
+- Boot button (GPIO 0 on most boards)
+
+Also compatible with:
+- ESP8266
+- STM32 with FreeRTOS
+- Any Arduino-compatible board with FreeRTOS support
+
+## Expected Behavior
+
+1. **LED Blinking**: LED blinks at varying rates (controlled by worker thread and timer ISR)
+2. **Button Press**: Pressing the boot button triggers a fast blink burst
+3. **Timer Events**: Every 7 seconds, hardware timer toggles blink rate
+4. **Thread Updates**: Worker thread changes blink interval every 3 seconds
+5. **Statistics**: Serial output shows counters and current state every 5 seconds
+
+## Key Components
+
+### Queue Implementation
+
+```cpp
+// Required global queue
+QueueHandle_t tsQueue;
+uint8_t tsQueueData[TS_QUEUE_LEN * sizeof(_task_request_t)];
+StaticQueue_t tsQueueBuffer;
+
+// Required enqueue function
+bool _task_enqueue_request(_task_request_t* req) {
+  if (xPortInIsrContext()) {
+    // ISR context
+    BaseType_t xHigherPriorityTaskWokenByPost = pdFALSE;
+    BaseType_t rc = xQueueSendFromISR(tsQueue, req, &xHigherPriorityTaskWokenByPost);
+    if (xHigherPriorityTaskWokenByPost) portYIELD_FROM_ISR();
+    return (rc == pdTRUE);
+  }
+  else {
+    // Normal task context
+    return (xQueueSend(tsQueue, req, pdMS_TO_TICKS(TS_ENQUEUE_WAIT_MS)) == pdTRUE);
+  }
+}
+
+// Required dequeue function
+bool _task_dequeue_request(_task_request_t* req) {
+  return (xQueueReceive(tsQueue, req, TS_DEQUEUE_WAIT_MS) == pdTRUE);
+}
+```
+
+### Safe Task Control from ISR
+
+```cpp
+void IRAM_ATTR buttonISR() {
+  // Signal StatusRequest from ISR (thread-safe)
+  ts.requestAction(&buttonPressed, TASK_SR_REQUEST_SIGNALCOMPLETE, 0, 0, 0, 0, 0);
+  isrTriggers++;
+}
+
+void IRAM_ATTR timerISR() {
+  // Change task interval from ISR (thread-safe)
+  ts.requestAction(&tBlink, TASK_REQUEST_SETINTERVAL, newInterval, 0, 0, 0, 0);
+}
+```
+
+### Safe Task Control from Worker Thread
+
+```cpp
+void workerThread(void* parameter) {
+  while (true) {
+    vTaskDelay(pdMS_TO_TICKS(3000));
+
+    // Safely adjust blink interval from worker thread
+    uint32_t newInterval = 300 + (counter % 5) * 100;
+    ts.requestAction(&tBlink, TASK_REQUEST_SETINTERVAL, newInterval, 0, 0, 0, 0);
+  }
+}
+```
+
+## Building and Running
+
+### PlatformIO
+
+```bash
+# Navigate to example directory
+cd lib/TaskScheduler/examples/Scheduler_example30_THREAD_SAFE
+
+# Build and upload
+pio run -t upload
+
+# Monitor serial output
+pio device monitor
+```
+
+### Arduino IDE
+
+1. Open `src/main.cpp` as a `.ino` file
+2. Install TaskScheduler library (version 3.8.0 or newer)
+3. Select ESP32 board
+4. Add to Arduino IDE preprocessor defines:
+   ```
+   -D_TASK_THREAD_SAFE
+   -D_TASK_STATUS_REQUEST
+   -D_TASK_TIMEOUT
+   -D_TASK_ISR_SUPPORT
+   ```
+5. Compile and upload
+
+## Serial Output Example
+
+```
+===========================================
+TaskScheduler Example 30: _TASK_THREAD_SAFE
+===========================================
+
+Task request queue created (size: 16)
+Button interrupt attached (press boot button)
+Hardware timer started (triggers every 7 seconds)
+Worker thread created
+
+--- System initialized ---
+Expected behavior:
+1. LED blinks at variable rate
+2. Press button for fast blink burst
+3. Timer ISR changes rate every 7s
+4. Worker thread adjusts rate every 3s
+5. All operations are thread-safe!
+
+[5123] Blink #10 (ISR triggers: 2, Thread updates: 1)
+Button pressed! Starting fast blink sequence...
+
+=== Statistics at 10000 ms ===
+Total blinks: 45
+ISR triggers: 2
+Thread updates: 3
+Current blink interval: 400 ms
+================================
+```
+
+## Configuration
+
+Adjust these constants in `main.cpp`:
+
+```cpp
+#define TS_QUEUE_LEN        16    // Request queue size (increase if overflow occurs)
+#define TS_ENQUEUE_WAIT_MS  10    // Max wait for enqueue (ms)
+#define TS_DEQUEUE_WAIT_MS  0     // No wait for dequeue
+```
+
+## Troubleshooting
+
+### Queue Overflow
+If you see "Failed to enqueue request" messages:
+- Increase `TS_QUEUE_LEN`
+- Increase `TS_ENQUEUE_WAIT_MS`
+- Reduce request frequency
+
+### Watchdog Timeouts
+If the ESP32 reboots with watchdog errors:
+- Ensure `ts.execute()` runs frequently in loop()
+- Check that no task blocks for too long
+- Reduce worker thread priority
+
+### Compilation Errors
+Ensure all compile flags are set in `platformio.ini`:
+- `_TASK_THREAD_SAFE` (required)
+- `_TASK_STATUS_REQUEST` (for button example)
+- `_TASK_ISR_SUPPORT` (for ESP ISR methods)
+
+## Learning Points
+
+### ✅ DO:
+- Always use `requestAction()` from ISRs and worker threads
+- Implement both enqueue and dequeue functions
+- Size the queue based on request frequency
+- Mark ISR functions with `IRAM_ATTR` (ESP32/ESP8266)
+
+### ❌ DON'T:
+- Call task methods directly from ISRs or other threads
+- Skip queue implementation (required for _TASK_THREAD_SAFE)
+- Forget to process requests (automatically done in `execute()`)
+- Block in ISRs waiting for queue space
+
+## Related Examples
+
+- **Example 27**: PlatformIO project structure
+- **Example 28**: Tickless operation with FreeRTOS
+- **Example 04/05**: StatusRequest basics
+
+## Further Reading
+
+- [TaskScheduler Wiki](https://github.com/arkhipenko/TaskScheduler/wiki)
+- TaskScheduler_THREAD_SAFE.md in your project root
+- FreeRTOS queue documentation
+- ESP32 interrupt handling
+
+## License
+
+Same as TaskScheduler library (see library LICENSE file)
+
+## Version
+
+Created for TaskScheduler v3.8.0+
+Updated for TaskScheduler v4.0.0 (October 2024)

+ 44 - 0
examples/Scheduler_example30_THREAD_SAFE/platformio.ini

@@ -0,0 +1,44 @@
+; PlatformIO Project Configuration File
+;
+; TaskScheduler Example 30: _TASK_THREAD_SAFE
+;
+; This example demonstrates the use of _TASK_THREAD_SAFE compile option
+; for safe interaction with TaskScheduler from multiple threads and ISRs.
+;
+; Demonstrates:
+; - FreeRTOS queue implementation for request handling
+; - Safe task control from ISR context
+; - Safe task control from worker threads
+; - StatusRequest signaling from interrupts
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[platformio]
+default_envs = esp32dev
+
+[env:esp32dev]
+platform = espressif32
+board = esp32dev
+framework = arduino
+
+[env]
+lib_deps =
+    arkhipenko/TaskScheduler @ ^4.0.0
+
+build_flags =
+    ; Core thread safety features
+    -D _TASK_THREAD_SAFE         ; Enable thread-safe operations
+    -D _TASK_HEADER_AND_CPP      ; Enable CPP compilation
+
+    ; Supporting features
+    -D _TASK_STATUS_REQUEST      ; Enable StatusRequest support
+    -D _TASK_TIMEOUT             ; Enable timeout support
+    -D _TASK_TIMECRITICAL        ; Enable timing diagnostics
+    -D _TASK_ISR_SUPPORT         ; Enable ISR-safe methods (ESP only)
+
+    ; Debug options
+    -D _DEBUG_
+
+monitor_speed = 115200
+upload_speed = 921600

+ 310 - 0
examples/Scheduler_example30_THREAD_SAFE/src/main.cpp

@@ -0,0 +1,310 @@
+/*
+ * TaskScheduler Example 30: _TASK_THREAD_SAFE
+ *
+ * This example demonstrates the use of the _TASK_THREAD_SAFE compile option
+ * for safe multi-threaded operation with TaskScheduler.
+ *
+ * Features demonstrated:
+ * 1. FreeRTOS queue implementation for thread-safe request handling
+ * 2. Task control from hardware timer ISR
+ * 3. Task control from FreeRTOS worker thread
+ * 4. StatusRequest signaling from ISR
+ * 5. Safe parameter updates from different contexts
+ *
+ * Hardware: ESP32 (or any platform with FreeRTOS support)
+ *
+ * Expected behavior:
+ * - LED blinks at varying rates
+ * - Button press triggers immediate blink from ISR
+ * - Worker thread adjusts blink rate periodically
+ * - All operations are thread-safe via request queue
+ */
+
+#include <Arduino.h>
+#include <freertos/FreeRTOS.h>
+#include <freertos/task.h>
+#include <freertos/queue.h>
+
+// Must define _TASK_THREAD_SAFE before including TaskScheduler
+// (or define it in platformio.ini build_flags)
+#include <TaskSchedulerDeclarations.h>
+
+// ============================================
+// Configuration
+// ============================================
+#ifndef LED_BUILTIN
+#define LED_BUILTIN 2
+#endif
+
+#define LED_PIN             LED_BUILTIN
+#define BUTTON_PIN          0              // Boot button on most ESP32 boards
+
+#define TS_QUEUE_LEN        16             // Task request queue length
+#define TS_ENQUEUE_WAIT_MS  10             // Max wait time for enqueue (ms)
+#define TS_DEQUEUE_WAIT_MS  0              // No wait for dequeue
+
+// ============================================
+// Global Variables
+// ============================================
+
+// Task Scheduler queue (for thread-safe operations)
+QueueHandle_t tsQueue;
+uint8_t tsQueueData[TS_QUEUE_LEN * sizeof(_task_request_t)];
+StaticQueue_t tsQueueBuffer;
+
+// Scheduler
+Scheduler ts;
+
+// Status request for ISR signaling
+StatusRequest buttonPressed;
+
+// Task counters
+volatile uint32_t blinkCount = 0;
+volatile uint32_t isrTriggers = 0;
+volatile uint32_t threadUpdates = 0;
+
+// ============================================
+// Task Queue Implementation (Required for _TASK_THREAD_SAFE)
+// ============================================
+
+/**
+ * Enqueue a task request (called from any thread/ISR)
+ * This function is required when _TASK_THREAD_SAFE is enabled
+ */
+bool _task_enqueue_request(_task_request_t* req) {
+  if (xPortInIsrContext()) {
+    // Called from ISR context
+    BaseType_t xHigherPriorityTaskWokenByPost = pdFALSE;
+    BaseType_t rc = xQueueSendFromISR(tsQueue, req, &xHigherPriorityTaskWokenByPost);
+    if (xHigherPriorityTaskWokenByPost) {
+      portYIELD_FROM_ISR();
+    }
+    return (rc == pdTRUE);
+  }
+  else {
+    // Called from normal task context
+    return (xQueueSend(tsQueue, req, pdMS_TO_TICKS(TS_ENQUEUE_WAIT_MS)) == pdTRUE);
+  }
+}
+
+/**
+ * Dequeue a task request (called by scheduler)
+ * This function is required when _TASK_THREAD_SAFE is enabled
+ */
+bool _task_dequeue_request(_task_request_t* req) {
+  if (xPortInIsrContext()) {
+    // Called from ISR context (shouldn't normally happen)
+    BaseType_t xHigherPriorityTaskWokenByPost = pdFALSE;
+    BaseType_t rc = xQueueReceiveFromISR(tsQueue, req, &xHigherPriorityTaskWokenByPost);
+    if (xHigherPriorityTaskWokenByPost) {
+      portYIELD_FROM_ISR();
+    }
+    return (rc == pdTRUE);
+  }
+  else {
+    // Called from normal task context
+    return (xQueueReceive(tsQueue, req, TS_DEQUEUE_WAIT_MS) == pdTRUE);
+  }
+}
+
+// ============================================
+// Task Callbacks
+// ============================================
+
+/**
+ * LED blink task callback
+ */
+void blinkCallback() {
+  digitalWrite(LED_PIN, !digitalRead(LED_PIN));
+  blinkCount++;
+
+  if (blinkCount % 10 == 0) {
+    Serial.printf("[%lu] Blink #%lu (ISR triggers: %lu, Thread updates: %lu)\n",
+                  millis(), blinkCount, isrTriggers, threadUpdates);
+  }
+}
+
+Task tBlink(500, TASK_FOREVER, &blinkCallback, &ts, true);
+
+/**
+ * Fast blink task (triggered by button press)
+ */
+void fastBlinkCallback() {
+  digitalWrite(LED_PIN, !digitalRead(LED_PIN));
+}
+
+Task tFastBlink(100, 10, &fastBlinkCallback, &ts, false);
+
+/**
+ * Statistics task callback
+ */
+void statsCallback() {
+  Serial.printf("\n=== Statistics at %lu ms ===\n", millis());
+  Serial.printf("Total blinks: %lu\n", blinkCount);
+  Serial.printf("ISR triggers: %lu\n", isrTriggers);
+  Serial.printf("Thread updates: %lu\n", threadUpdates);
+  Serial.printf("Current blink interval: %lu ms\n", tBlink.getInterval());
+
+#ifdef _TASK_TIMECRITICAL
+  if (ts.isOverrun()) {
+    Serial.println("WARNING: Scheduler overrun detected!");
+  }
+#endif
+
+  Serial.println("================================\n");
+}
+
+Task tStats(5000, TASK_FOREVER, &statsCallback, &ts, true);
+
+// ============================================
+// ISR Handlers
+// ============================================
+
+/**
+ * Button ISR - triggers fast blink using thread-safe requestAction
+ */
+void IRAM_ATTR buttonISR() {
+  // Signal the status request from ISR
+  // This is thread-safe via requestAction
+  ts.requestAction(&buttonPressed, TASK_SR_REQUEST_SIGNALCOMPLETE, 0, 0, 0, 0, 0);
+  isrTriggers++;
+}
+
+/**
+ * Timer ISR - adjusts blink rate using thread-safe requestAction
+ */
+void IRAM_ATTR timerISR() {
+  // Change the blink interval from ISR (thread-safe)
+  static uint32_t nextInterval = 1000;
+
+  ts.requestAction(&tBlink, TASK_REQUEST_SETINTERVAL, nextInterval, 0, 0, 0, 0);
+
+  // Alternate between fast and slow
+  nextInterval = (nextInterval == 1000) ? 200 : 1000;
+}
+
+// ============================================
+// Worker Thread
+// ============================================
+
+/**
+ * Background worker thread that adjusts task parameters
+ * Demonstrates safe task manipulation from another FreeRTOS task
+ */
+void workerThread(void* parameter) {
+  uint32_t counter = 0;
+
+  while (true) {
+    vTaskDelay(pdMS_TO_TICKS(3000));  // Run every 3 seconds
+
+    counter++;
+
+    // Safely adjust the blink interval from worker thread
+    uint32_t newInterval = 300 + (counter % 5) * 100;  // 300-700ms range
+
+    // Use requestAction for thread-safe operation
+    bool success = ts.requestAction(&tBlink, TASK_REQUEST_SETINTERVAL, newInterval, 0, 0, 0, 0);
+
+    if (success) {
+      threadUpdates++;
+    } else {
+      Serial.println("ERROR: Failed to enqueue request (queue full?)");
+    }
+  }
+}
+
+// ============================================
+// Status Request Task
+// ============================================
+
+/**
+ * Task that waits for button press signal
+ */
+void buttonWatchCallback() {
+  Serial.println("Button pressed! Starting fast blink sequence...");
+
+  // Restart the fast blink task
+  // Direct call is safe because we're in scheduler context
+  tFastBlink.restart();
+}
+
+Task tButtonWatch(TASK_IMMEDIATE, TASK_FOREVER, &buttonWatchCallback, &ts, false);
+
+// ============================================
+// Setup and Main Loop
+// ============================================
+
+void setup() {
+  Serial.begin(115200);
+  delay(500);
+
+  Serial.println("\n\n===========================================");
+  Serial.println("TaskScheduler Example 30: _TASK_THREAD_SAFE");
+  Serial.println("===========================================\n");
+
+  // Initialize LED
+  pinMode(LED_PIN, OUTPUT);
+  digitalWrite(LED_PIN, LOW);
+
+  // Initialize button with pull-up
+  pinMode(BUTTON_PIN, INPUT_PULLUP);
+
+  // Create the task request queue
+  tsQueue = xQueueCreateStatic(
+    TS_QUEUE_LEN,
+    sizeof(_task_request_t),
+    tsQueueData,
+    &tsQueueBuffer
+  );
+
+  if (tsQueue == NULL) {
+    Serial.println("ERROR: Failed to create task queue!");
+    while (1) delay(1000);
+  }
+
+  Serial.printf("Task request queue created (size: %d)\n", TS_QUEUE_LEN);
+
+  // Set up button watch task to wait for button press signal
+  tButtonWatch.waitFor(&buttonPressed);
+
+  // Attach button interrupt
+  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);
+  Serial.println("Button interrupt attached (press boot button)");
+
+  // Create timer for periodic ISR (every 7 seconds)
+  hw_timer_t* timer = timerBegin(0, 80, true);  // Timer 0, prescaler 80 (1MHz), count up
+  timerAttachInterrupt(timer, &timerISR, true);
+  timerAlarmWrite(timer, 7000000, true);  // 7 seconds in microseconds, auto-reload
+  timerAlarmEnable(timer);
+  Serial.println("Hardware timer started (triggers every 7 seconds)");
+
+  // Create worker thread
+  xTaskCreate(
+    workerThread,
+    "WorkerThread",
+    4096,
+    NULL,
+    1,  // Priority
+    NULL
+  );
+  Serial.println("Worker thread created");
+
+  Serial.println("\n--- System initialized ---");
+  Serial.println("Expected behavior:");
+  Serial.println("1. LED blinks at variable rate");
+  Serial.println("2. Press button for fast blink burst");
+  Serial.println("3. Timer ISR changes rate every 7s");
+  Serial.println("4. Worker thread adjusts rate every 3s");
+  Serial.println("5. All operations are thread-safe!\n");
+
+  delay(1000);
+}
+
+void loop() {
+  // Run the scheduler
+  // It will automatically process queued requests via processRequests()
+  ts.execute();
+
+  // Small delay to prevent watchdog issues
+  delay(1);
+}

+ 1 - 1
library.json

@@ -16,7 +16,7 @@
       "maintainer": true
     }
   ],
-  "version": "4.0.0",
+  "version": "4.0.1",
   "frameworks": "arduino",
   "platforms": "*"
 }

+ 1 - 1
library.properties

@@ -1,5 +1,5 @@
 name=TaskScheduler
-version=4.0.0
+version=4.0.1
 author=Anatoli Arkhipenko <arkhipenko@hotmail.com>
 maintainer=Anatoli Arkhipenko <arkhipenko@hotmail.com>
 sentence=Cooperative multitasking for Arduino, ESPx, STM32 and other microcontrollers.

+ 6 - 12
src/TaskScheduler.h

@@ -290,6 +290,12 @@ v4.0.0:
         - bug: incorrect behavior of the StatusRequest timeout functionality due to uninitialized timeout variable
         - update: addedd Doxygen comments to all methods and variables
          -update: added a number of compile and unit tests for CI/CD
+
+v4.0.1:
+    2025-10-07:
+        - bug: removed leftover iMutex variable
+        - added example30: _TASK_THREAD_SAFE
+
 */
 
 #include "TaskSchedulerDeclarations.h"
@@ -649,10 +655,6 @@ void Task::set(unsigned long aInterval, long aIterations, TaskCallback aCallback
     setInterval(aInterval);
     iSetIterations = aIterations;
     iIterations = aIterations;
-#ifdef _TASK_THREAD_SAFE
-    iMutex = iMutex - 1;
-#endif  // _TASK_THREAD_SAFE
-
 }
 
 /** Sets number of iterations for the task
@@ -660,16 +662,8 @@ void Task::set(unsigned long aInterval, long aIterations, TaskCallback aCallback
  * @param aIterations - number of iterations, use -1 for no limit
  */
 void Task::setIterations(long aIterations) {
-#ifdef _TASK_THREAD_SAFE
-    iMutex = iMutex + 1;
-#endif  // _TASK_THREAD_SAFE
-
     iSetIterations = aIterations;
     iIterations = aIterations;
-
-#ifdef _TASK_THREAD_SAFE
-    iMutex = iMutex - 1;
-#endif  // _TASK_THREAD_SAFE
 }
 
 #ifndef _TASK_OO_CALLBACKS

+ 3 - 2
src/TaskSchedulerDeclarations.h

@@ -125,8 +125,9 @@
  * For non-Arduino IDE platforms that require explicit CPP compilation.
  * 
  * @par _TASK_THREAD_SAFE
- * Enable additional checking for thread safety.
- * Uses an internal mutex to protect task scheduling methods from preemption.
+ * Enable additional functionality to request processing in a thread-safe manner.
+ * Uses a request queue to safely invoke task control methods from other threads or interrupts.
+ * Also enables basic mutex locking to prevent concurrent access issues.
  * Recommended for ESP32 and other MCUs running under preemptive schedulers like FreeRTOS.
  * 
  */