Files
mixly3-server/arduino-libs/arduino-cli/libraries/CoopTask/examples/mutex/mutex.ino

253 lines
7.7 KiB
C++

/*
Name: mutex.ino
Created: 2019-08-04 22:40:11
Author: dok@dok-net.net
*/
#include <CoopTask.h>
#include <CoopSemaphore.h>
#include <CoopMutex.h>
#define USE_BUILTIN_TASK_SCHEDULER
CoopMutex serialMutex;
CoopMutex mutex;
CoopTaskBase* hasMutex(nullptr);
void haveMutex()
{
if (hasMutex)
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" called haveMutex, despite "));
Serial.print(hasMutex->name());
Serial.println(F(" is known to have mutex."));
return;
}
hasMutex = CoopTaskBase::self();
}
void yieldMutex()
{
if (hasMutex != CoopTaskBase::self())
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" called yieldMutex, but no task currently has the mutex."));
return;
}
hasMutex = nullptr;
}
CoopTask<int>* firstTask;
CoopTask<int>* secondTask;
CoopTask<int>* thirdTask;
void setup() {
#ifdef ESP8266
Serial.begin(74880);
#else
Serial.begin(115200);
#endif
while (!Serial) {}
delay(500);
Serial.println(F("Mutex test"));
#if defined(ESP8266) && defined(USE_BUILTIN_TASK_SCHEDULER)
CoopTaskBase::useBuiltinScheduler();
#endif
firstTask = createCoopTask(F("first"), []()
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" starts"));
}
for (int i = 0; i < 30; ++i)
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" locks mutex"));
}
{
CoopMutexLock lock(mutex);
if (!lock) {
CoopMutexLock serialLock(serialMutex);
Serial.print(F("failed to lock mutex in "));
Serial.println(CoopTaskBase::self()->name());
}
haveMutex();
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" has mutex"));
}
yield();
yieldMutex();
}
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" runs ("));
Serial.print(i);
Serial.println(')');
}
yield();
}
CoopMutexLock serialLock(serialMutex);
Serial.print(F("exiting from task "));
Serial.println(CoopTaskBase::self()->name());
return 0;
}
#if defined(ESP8266) || defined(ESP32)
);
#else
, 0x120);
#endif
if (!firstTask) Serial.println(F("firstTask not created"));
secondTask = createCoopTask(F("second"), []()
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" starts"));
}
for (int i = 0; i < 30; ++i)
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" locks mutex"));
}
{
CoopMutexLock lock(mutex);
if (!lock) {
CoopMutexLock serialLock(serialMutex);
Serial.print(F("failed to lock mutex in "));
Serial.println(CoopTaskBase::self()->name());
}
haveMutex();
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" has mutex"));
}
yield();
yieldMutex();
}
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" runs ("));
Serial.print(i);
Serial.println(')');
}
yield();
}
CoopMutexLock serialLock(serialMutex);
Serial.print(F("exiting from task "));
Serial.println(CoopTaskBase::self()->name());
return 0;
}
#if defined(ESP8266) || defined(ESP32)
);
#else
, 0x120);
#endif
if (!secondTask) Serial.println(F("secondTask not created"));
thirdTask = createCoopTask(F("third"), []()
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" starts"));
}
for (int i = 0; i < 10; ++i)
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" locks mutex"));
}
{
CoopMutexLock lock(mutex);
if (!lock) {
CoopMutexLock serialLock(serialMutex);
Serial.print(F("failed to lock mutex in "));
Serial.println(CoopTaskBase::self()->name());
}
haveMutex();
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.println(F(" has mutex"));
}
yield();
yieldMutex();
}
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" runs ("));
Serial.print(i);
Serial.println(')');
}
yield();
}
for (int i = 0; i < 10; ++i)
{
{
CoopMutexLock serialLock(serialMutex);
Serial.print(CoopTaskBase::self()->name());
Serial.print(F(" still runs ("));
Serial.print(i);
Serial.println(')');
}
yield();
}
CoopMutexLock serialLock(serialMutex);
Serial.print(F("exiting from task "));
Serial.println(CoopTaskBase::self()->name());
return 0;
}
#if defined(ESP8266) || defined(ESP32)
);
#else
, 0x120);
#endif
if (!thirdTask) Serial.println(F("thirdTask not created"));
#ifdef ESP32
Serial.print(F("Loop free stack = ")); Serial.println(uxTaskGetStackHighWaterMark(NULL));
#endif
}
void taskReaper(const CoopTaskBase* const task)
{
delete task;
}
// the loop function runs over and over again until power down or reset
void loop()
{
#if defined(ESP8266) && defined(USE_BUILTIN_TASK_SCHEDULER)
if (firstTask && !*firstTask)
{
taskReaper(firstTask); firstTask = nullptr;
}
if (secondTask && !*secondTask)
{
taskReaper(secondTask); secondTask = nullptr;
}
if (thirdTask && !*thirdTask)
{
taskReaper(thirdTask); thirdTask = nullptr;
}
#else
runCoopTasks(taskReaper);
#endif
}