diff --git a/RCSwitch.cpp b/RCSwitch.cpp index ac55acb..26f56ac 100644 --- a/RCSwitch.cpp +++ b/RCSwitch.cpp @@ -33,6 +33,7 @@ */ #include "RCSwitch.h" +#include #ifdef RaspberryPi // PROGMEM and _P functions are for AVR based microprocessors, @@ -103,7 +104,13 @@ const unsigned int RCSwitch::nSeparationLimit = 4300; // according to discussion on issue #14 it might be more suitable to set the separation // limit to the same time as the 'low' part of the sync signal for the current protocol. unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES]; -#endif +#if defined(WITH_LOCKS) +volatile bool RCSwitch::useLocks = false; +std::mutex RCSwitch::mutex; +std::condition_variable RCSwitch::receiveGuard; +#endif // WITH_LOCKS + +#endif // !RCSwitchDisableReceiving RCSwitch::RCSwitch() { this->nTransmitterPin = -1; @@ -601,6 +608,22 @@ static inline unsigned int diff(int A, int B) { return abs(A - B); } +#if defined(WITH_LOCKS) +void RCSwitch::enableLocks() { + this->useLocks = true; +} +void RCSwitch::wait() { + assert(useLocks); + if (!useLocks) { + return; + } + while (!available()) { + std::unique_lock lock(this->mutex); + receiveGuard.wait(lock); + } +} +#endif + /** * */ @@ -653,10 +676,22 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun } if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise + #if defined(WITH_LOCKS) + std::unique_lock lock(mutex, std::defer_lock); + if (useLocks) { + lock.lock(); + } + #endif + // The following code is lock-guarded when using locks. RCSwitch::nReceivedValue = code; RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; RCSwitch::nReceivedDelay = delay; RCSwitch::nReceivedProtocol = p; + #if defined(WITH_LOCKS) + if (useLocks) { + receiveGuard.notify_all(); + } + #endif return true; } diff --git a/RCSwitch.h b/RCSwitch.h index b7755e0..9a346d0 100644 --- a/RCSwitch.h +++ b/RCSwitch.h @@ -47,6 +47,15 @@ #include "WProgram.h" #endif +#if defined(WITH_LOCKS) && !defined(RaspberryPi) + #error "Locks are not supported outside Raspberry Pi!" +#endif + +#if defined(WITH_LOCKS) + #include + #include +#endif + #include @@ -148,6 +157,14 @@ class RCSwitch { void setProtocol(int nProtocol); void setProtocol(int nProtocol, int nPulseLength); + #if defined(WITH_LOCKS) + // Enabled the handling of locks. + // If enabled, the caller can use the wait() function to wait for data. + void enableLocks(); + void wait(); + #endif + + private: char* getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus); char* getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus); @@ -160,6 +177,13 @@ class RCSwitch { static bool receiveProtocol(const int p, unsigned int changeCount); int nReceiverInterrupt; #endif + + #if defined(WITH_LOCKS) + static std::mutex mutex; + static std::condition_variable receiveGuard; + static volatile bool useLocks; + #endif + int nTransmitterPin; int nRepeatTransmit;