#include "RadiolibThreadedDevice.h" #include constexpr const char* TAG = "RadiolibThreadedDevice"; bool RadiolibThreadedDevice::start(const Modulation modulation) { auto lock = getMutex().asScopedLock(); if (!isCapableOf(modulation)) { TT_LOG_E(TAG, "Can't start device \"%s\", not capable of modulation \"%s\"", getName().c_str(), toString(modulation)); return false; } lock.lock(); if (thread != nullptr && thread->getState() != tt::Thread::State::Stopped) { TT_LOG_W(TAG, "Already started"); return true; } threadInterrupted = false; TT_LOG_I(TAG, "Starting thread"); setState(State::PendingOn); thread = std::make_unique( threadName, threadSize, [this, modulation]() { return this->threadMain(modulation); } ); thread->setPriority(tt::Thread::Priority::High); thread->start(); TT_LOG_I(TAG, "Starting finished"); return true; } bool RadiolibThreadedDevice::stop() { auto lock = getMutex().asScopedLock(); lock.lock(); setState(State::PendingOff); if (thread != nullptr) { threadInterrupted = true; interruptSignal(); // Detach thread, it will auto-delete when leaving the current scope auto old_thread = std::move(thread); if (old_thread->getState() != tt::Thread::State::Stopped) { // Unlock so thread can lock lock.unlock(); // Wait for thread to finish old_thread->join(); // Re-lock to continue logic below lock.lock(); } } setState(State::Off); return true; } bool RadiolibThreadedDevice::isThreadInterrupted() const { auto lock = getMutex().asScopedLock(); lock.lock(); return threadInterrupted; } int32_t RadiolibThreadedDevice::threadMain(const Modulation modulation) { int rc = doBegin(modulation); if (rc != 0) { return rc; } setState(State::On); while (!isThreadInterrupted()) { doListen(); // Thread might've been interrupted in the meanwhile if (isThreadInterrupted()) { break; } if (getTxQueueSize() > 0) { doTransmit(); } else { doReceive(); } } doEnd(); return 0; }