void CPanasonic::UnloadNodes() { int iRetryCounter = 0; boost::lock_guard<boost::mutex> l(m_mutex); m_ios.stop(); // stop the service if it is running sleep_milliseconds(100); while ((!m_pNodes.empty()) || (!m_ios.stopped()) && (iRetryCounter < 15)) { std::vector<boost::shared_ptr<CPanasonicNode> >::iterator itt; for (itt = m_pNodes.begin(); itt != m_pNodes.end(); ++itt) { (*itt)->StopRequest(); if (!(*itt)->IsBusy()) { _log.Log(LOG_NORM, "Panasonic Plugin: (%s) Removing device.", (*itt)->m_Name.c_str()); m_pNodes.erase(itt); break; } } iRetryCounter++; sleep_milliseconds(500); } m_pNodes.clear(); }
bool CLogitechMediaServer::StopHardware() { StopHeartbeatThread(); try { if (m_thread) { m_stoprequested = true; m_thread->join(); m_thread.reset(); //Make sure all our background workers are stopped int iRetryCounter = 0; while ((m_iThreadsRunning > 0) && (iRetryCounter<15)) { sleep_milliseconds(500); iRetryCounter++; } } } catch (...) { //Don't throw from a Stop command } m_bIsStarted = false; return true; }
void CHardwareMonitor::Do_Work() { _log.Log(LOG_STATUS, "Hardware Monitor: Started"); int msec_counter = 0; int sec_counter = POLL_INTERVAL - 3; while (!m_stoprequested) { sleep_milliseconds(500); msec_counter++; if (msec_counter == 2) { msec_counter = 0; sec_counter++; if (sec_counter % 12 == 0) { m_LastHeartbeat = mytime(NULL); } if (sec_counter%POLL_INTERVAL == 0) { FetchData(); } } } _log.Log(LOG_STATUS,"Hardware Monitor: Stopped..."); }
void C1Wire::SwitchThread() { int pollPeriod = m_switchThreadPeriod; // Rescan the bus once every 10 seconds if requested #define HARDWARE_RESCAN_PERIOD 10000 int rescanIterations = HARDWARE_RESCAN_PERIOD / pollPeriod; if (0 == rescanIterations) rescanIterations = 1; int iteration = 0; m_bSwitchFirstTime = true; while (!m_stoprequested) { sleep_milliseconds(pollPeriod); if (0 == iteration++ % rescanIterations) // may glitch on overflow, not disastrous { if (m_bSwitchFirstTime) { m_bSwitchFirstTime = false; BuildSwitchList(); } } PollSwitches(); } _log.Log(LOG_STATUS, "1-Wire: Switch thread terminating"); }
void AsyncSerial::writeEnd(const boost::system::error_code& error) { if(!error) { boost::lock_guard<boost::mutex> l(pimpl->writeQueueMutex); if(pimpl->writeQueue.empty()) { pimpl->writeBuffer.reset(); pimpl->writeBufferSize=0; sleep_milliseconds(75); return; } pimpl->writeBufferSize=pimpl->writeQueue.size(); pimpl->writeBuffer.reset(new char[pimpl->writeQueue.size()]); copy(pimpl->writeQueue.begin(),pimpl->writeQueue.end(), pimpl->writeBuffer.get()); pimpl->writeQueue.clear(); async_write(pimpl->port,boost::asio::buffer(pimpl->writeBuffer.get(), pimpl->writeBufferSize), boost::bind(&AsyncSerial::writeEnd, this, boost::asio::placeholders::error)); } else { try { setErrorStatus(true); doClose(); } catch (...) { } } }
void CPanasonic::Do_Work() { int scounter = 0; ReloadNodes(); while (!m_stoprequested) { if (scounter++ >= (m_iPollInterval * 2)) { boost::lock_guard<boost::mutex> l(m_mutex); scounter = 0; bool bWorkToDo = false; std::vector<boost::shared_ptr<CPanasonicNode> >::iterator itt; for (itt = m_pNodes.begin(); itt != m_pNodes.end(); ++itt) { if (!(*itt)->IsBusy()) { _log.Log(LOG_NORM, "Panasonic Plugin: (%s) - Restarting thread.", (*itt)->m_Name.c_str()); (*itt)->StartThread(); } if ((*itt)->IsOn()) bWorkToDo = true; } } sleep_milliseconds(500); } UnloadNodes(); _log.Log(LOG_STATUS, "Panasonic Plugin: Worker stopped..."); }
void CPhilipsHue::Do_Work() { int msec_counter = 0; int sec_counter = HUE_POLL_INTERVAL-2; _log.Log(LOG_STATUS,"Philips Hue: Worker started..."); while (!m_stoprequested) { sleep_milliseconds(500); msec_counter++; if (msec_counter == 2) { msec_counter = 0; sec_counter++; if (sec_counter % HUE_POLL_INTERVAL == 0) { m_LastHeartbeat = mytime(NULL); GetStates(); } } } _log.Log(LOG_STATUS,"Philips Hue: Worker stopped..."); }
void Comm5TCP::Do_Work() { bool bFirstTime = true; int count = 0; while (!m_stoprequested) { m_LastHeartbeat = mytime(NULL); if (bFirstTime) { bFirstTime = false; if (!mIsConnected) { m_rxbufferpos = 0; connect(m_szIPAddress, m_usIPPort); } } else { sleep_milliseconds(40); update(); if (count++ >= 100) { count = 0; querySensorState(); } } } _log.Log(LOG_STATUS, "Comm5 MA-5XXX: TCP/IP Worker stopped..."); }
void MochadTCP::Do_Work() { bool bFirstTime = true; while (!m_stoprequested) { time_t atime = mytime(NULL); struct tm ltime; localtime_r(&atime, <ime); if (ltime.tm_sec % 12 == 0) { mytime(&m_LastHeartbeat); } if (bFirstTime) { bFirstTime = false; if (!mIsConnected) { m_rxbufferpos = 0; connect(m_szIPAddress, m_usIPPort); } } else { sleep_milliseconds(40); update(); } } _log.Log(LOG_STATUS,"Mochad: TCP/IP Worker stopped..."); }
void CPanasonic::ReloadNodes() { UnloadNodes(); //m_ios.reset(); // in case this is not the first time in std::vector<std::vector<std::string> > result; result = m_sql.safe_query("SELECT ID,Name,MacAddress,Timeout FROM WOLNodes WHERE (HardwareID==%d)", m_HwdID); if (result.size() > 0) { boost::lock_guard<boost::mutex> l(m_mutex); // create a vector to hold the nodes for (std::vector<std::vector<std::string> >::const_iterator itt = result.begin(); itt != result.end(); ++itt) { std::vector<std::string> sd = *itt; boost::shared_ptr<CPanasonicNode> pNode = (boost::shared_ptr<CPanasonicNode>) new CPanasonicNode(m_HwdID, m_iPollInterval, m_iPingTimeoutms, sd[0], sd[1], sd[2], sd[3]); m_pNodes.push_back(pNode); } // start the threads to control each Panasonic TV for (std::vector<boost::shared_ptr<CPanasonicNode> >::iterator itt = m_pNodes.begin(); itt != m_pNodes.end(); ++itt) { _log.Log(LOG_NORM, "Panasonic Plugin: (%s) Starting thread.", (*itt)->m_Name.c_str()); boost::thread* tAsync = new boost::thread(&CPanasonicNode::Do_Work, (*itt)); } sleep_milliseconds(100); //_log.Log(LOG_NORM, "Panasonic Plugin: Starting I/O service thread."); //boost::thread bt(boost::bind(&boost::asio::io_service::run, &m_ios)); } }
void ZWaveBase::Do_Work() { #ifdef WIN32 //prevent OpenZWave locale from taking over _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); #endif while (!m_stoprequested) { sleep_milliseconds(500); if (m_stoprequested) return; if (m_bInitState) { if (GetInitialDevices()) { m_bInitState=false; sOnConnected(this); } } else { GetUpdates(); if (m_bControllerCommandInProgress==true) { time_t atime=mytime(NULL); time_t tdiff=atime-m_ControllerCommandStartTime; if (tdiff>=CONTROLLER_COMMAND_TIMEOUT) { _log.Log(LOG_ERROR,"ZWave: Stopping Controller command (Timeout!)"); CancelControllerCommand(); } } } } }
void C1Wire::SensorThread() { int pollPeriod = m_sensorThreadPeriod; int pollIterations = 1; if (pollPeriod > 1000) { pollIterations = pollPeriod / 1000; pollPeriod = 1000; } int iteration = 0; m_bSensorFirstTime = true; while (!m_stoprequested) { sleep_milliseconds(pollPeriod); if (0 == iteration++ % pollIterations) // may glitch on overflow, not disastrous { if (m_bSensorFirstTime) { m_bSensorFirstTime = false; BuildSensorList(); } PollSensors(); } } _log.Log(LOG_STATUS, "1-Wire: Sensor thread terminating"); }
void CPanasonicNode::Do_Work() { m_Busy = true; if (DEBUG_LOGGING) _log.Log(LOG_NORM, "Panasonic Plugin: (%s) Entering work loop.", m_Name.c_str()); int iPollCount = 9; while (!m_stoprequested) { sleep_milliseconds(500); iPollCount++; if (iPollCount >= 10) { iPollCount = 0; try { std::string _volReply; std::string _muteReply; _volReply = handleWriteAndRead(buildXMLStringRendCtl("Get", "Volume")); if (_volReply != "ERROR") { int iVol = handleMessage(_volReply); m_CurrentStatus.Volume(iVol); if (m_CurrentStatus.Status() != MSTAT_ON && iVol > -1) { m_CurrentStatus.Status(MSTAT_ON); UpdateStatus(); } } else { if (m_CurrentStatus.Status() != MSTAT_OFF) { m_CurrentStatus.Clear(); m_CurrentStatus.Status(MSTAT_OFF); UpdateStatus(); } } //_muteReply = handleWriteAndRead(buildXMLStringRendCtl("Get", "Mute")); //_log.Log(LOG_NORM, "Panasonic Plugin: (%s) Mute reply - \r\n", m_Name.c_str(), _muteReply.c_str()); //if (_muteReply != "ERROR") //{ // m_CurrentStatus.Muted((handleMessage(_muteReply)==0) ? false : true); //} UpdateStatus(); } catch (std::exception& e) { _log.Log(LOG_ERROR, "Panasonic Plugin: (%s) Exception: %s", m_Name.c_str(), e.what()); } } } _log.Log(LOG_NORM, "Panasonic Plugin: (%s) Exiting work loop.", m_Name.c_str()); m_Busy = false; }
void CDomoticzHardwareBase::StopHeartbeatThread() { m_stopHeartbeatrequested = true; if (m_Heartbeatthread) { m_Heartbeatthread->join(); // Wait a while. The read thread might be reading. Adding this prevents a pointer error in the async serial class. sleep_milliseconds(10); } }
/* * Called after most socket or tun/tap operations, via the inline * function check_status(). * * Decide if we should print an error message, and see if we can * extract any useful info from the error, such as a Path MTU hint * from the OS. */ void x_check_status (int status, const char *description, struct link_socket *sock, struct tuntap *tt) { const int my_errno = (sock ? openvpn_errno_socket () : openvpn_errno ()); const char *extended_msg = NULL; msg (x_cs_verbose_level, "%s %s returned %d", sock ? proto2ascii (sock->info.proto, true) : "", description, status); if (status < 0) { struct gc_arena gc = gc_new (); #if EXTENDED_SOCKET_ERROR_CAPABILITY /* get extended socket error message and possible PMTU hint from OS */ if (sock) { int mtu; extended_msg = format_extended_socket_error (sock->sd, &mtu, &gc); if (mtu > 0 && sock->mtu != mtu) { sock->mtu = mtu; sock->info.mtu_changed = true; } } #elif defined(WIN32) /* get possible driver error from TAP-Win32 driver */ extended_msg = tap_win32_getinfo (tt, &gc); #endif if (!ignore_sys_error (my_errno)) { if (extended_msg) msg (x_cs_info_level, "%s %s [%s]: %s (code=%d)", description, sock ? proto2ascii (sock->info.proto, true) : "", extended_msg, strerror_ts (my_errno, &gc), my_errno); else msg (x_cs_info_level, "%s %s: %s (code=%d)", description, sock ? proto2ascii (sock->info.proto, true) : "", strerror_ts (my_errno, &gc), my_errno); if (x_cs_err_delay_ms) sleep_milliseconds (x_cs_err_delay_ms); } gc_free (&gc); } }
bool KMTronicSerial::WriteInt(const unsigned char *data, const size_t len, const bool bWaitForReturn) { if (!isOpen()) return false; m_bHaveReceived = false; write((const char*)data, len); if (!bWaitForReturn) return true; sleep_milliseconds(100); return (m_bHaveReceived == true); }
void MQTT::Do_Work() { bool bFirstTime=true; int msec_counter = 0; int sec_counter = 0; while (!m_stoprequested) { sleep_milliseconds(100); if (!bFirstTime) { int rc = loop(); if (rc) { if (rc != MOSQ_ERR_NO_CONN) { if (!m_stoprequested) { if (!m_bDoReconnect) { reconnect(); } } } } } msec_counter++; if (msec_counter == 10) { msec_counter = 0; sec_counter++; if (sec_counter % 12 == 0) { m_LastHeartbeat=mytime(NULL); } if (bFirstTime) { bFirstTime = false; ConnectInt(); } else { if (sec_counter % 30 == 0) { if (m_bDoReconnect) ConnectIntEx(); } } } } _log.Log(LOG_STATUS,"MQTT: Worker stopped..."); }
bool CDavisLoggerSerial::StopHardware() { m_stoprequested=true; if (m_thread) { m_thread->join(); } // Wait a while. The read thread might be reading. Adding this prevents a pointer error in the async serial class. sleep_milliseconds(10); terminate(); m_bIsStarted=false; return true; }
bool P1MeterSerial::StopHardware() { terminate(); m_stoprequested = true; if (m_thread) { m_thread->join(); // Wait a while. The read thread might be reading. Adding this prevents a pointer error in the async serial class. sleep_milliseconds(10); } m_bIsStarted = false; _log.Log(LOG_STATUS, "P1 Smart Meter: Serial Worker stopped..."); return true; }
bool CGpio::StartHardware() { m_stoprequested=false; // _log.Log(LOG_NORM,"GPIO: Starting hardware (debounce: %d ms, period: %d ms, poll interval: %d sec)", m_debounce, m_period, m_pollinterval); if (InitPins()) { /* Disabled for now, devices should be added manually (this was the old behaviour, which we'll follow for now). Keep code for possible future usage. if (!CreateDomoticzDevices()) { _log.Log(LOG_NORM, "GPIO: Error creating pins in DB, aborting..."); m_stoprequested=true; }*/ if (!m_stoprequested) { // Read all exported GPIO ports and set the device status accordingly. // No need for delayed startup and force update when no masters are able to connect. std::vector<std::vector<std::string> > result; result = m_sql.safe_query("SELECT ID FROM Users WHERE (RemoteSharing==1) AND (Active==1)"); if (result.size() > 0) { for (int i = 0; i < DELAYED_STARTUP_SEC; ++i) { sleep_milliseconds(1000); if (m_stoprequested) break; } _log.Log(LOG_NORM, "GPIO: Optional connected Master Domoticz now updates its status"); UpdateDeviceStates(true); } else UpdateDeviceStates(false); if (m_pollinterval > 0) m_thread_poller = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&CGpio::Poller, this))); } } else { _log.Log(LOG_NORM, "GPIO: No exported pins found, aborting..."); m_stoprequested=true; } m_bIsStarted=true; sOnConnected(this); StartHeartbeatThread(); return (m_thread != NULL); }
bool CGpio::InitPins() { int fd; bool db_state = false; char path[GPIO_MAX_PATH]; char szIdx[10]; char label[12]; std::vector<std::vector<std::string> > result; boost::mutex::scoped_lock lock(m_pins_mutex); pins.clear(); for (int gpio_pin = GPIO_PIN_MIN; gpio_pin <= GPIO_PIN_MAX; gpio_pin++) { snprintf(path, GPIO_MAX_PATH, "%s%d", GPIO_PATH, gpio_pin); fd = open(path, O_RDONLY); if (fd != -1) /* GPIO export found */ { result = m_sql.safe_query("SELECT nValue FROM DeviceStatus WHERE (HardwareID==%d) AND (Unit==%d)", m_HwdID, gpio_pin); if (result.size() > 0) db_state = atoi(result[0][0].c_str()); snprintf(label, sizeof(label), "GPIO pin %d", gpio_pin); pins.push_back(CGpioPin(gpio_pin, label, GPIORead(gpio_pin, "value"), GPIORead(gpio_pin, "direction"), GPIORead(gpio_pin, "edge"), GPIORead(gpio_pin, "active_low"), -1, db_state)); //_log.Log(LOG_NORM, "GPIO: Pin %d added (value: %d, direction: %d, edge: %d, active_low: %d, db_state: %d)", // gpio_pin, GPIORead(gpio_pin, "value"), GPIORead(gpio_pin, "direction"), GPIORead(gpio_pin, "edge"), GPIORead(gpio_pin, "active_low"), db_state); close(fd); if (GPIORead(gpio_pin, "direction") != 0) continue; snprintf(path, GPIO_MAX_PATH, "%s%d/value", GPIO_PATH, gpio_pin); fd = pins.back().SetReadValueFd(open(path, O_RDWR)); // O_RDWR seems mandatory to clear interrupt (not sure why?) if (fd != -1) { pinPass = gpio_pin; m_thread_interrupt[gpio_pin] = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&CGpio::InterruptHandler, this))); while (pinPass != -1) sleep_milliseconds(1); } } } return (pins.size() > 0); }
void CLogitechMediaServer::Do_Work() { int mcounter = 0; int scounter = 0; bool bFirstTime = true; _log.Log(LOG_STATUS, "Logitech Media Server: Worker started..."); ReloadNodes(); ReloadPlaylists(); while (!m_stoprequested) { sleep_milliseconds(500); mcounter++; if (mcounter == 2) { mcounter = 0; scounter++; if ((scounter >= m_iPollInterval) || (bFirstTime)) { boost::lock_guard<boost::mutex> l(m_mutex); scounter = 0; bFirstTime = false; GetPlayerInfo(); std::vector<LogitechMediaServerNode>::const_iterator itt; for (itt = m_nodes.begin(); itt != m_nodes.end(); ++itt) { if (m_stoprequested) return; if (m_iThreadsRunning < 1000) { m_iThreadsRunning++; boost::thread t(boost::bind(&CLogitechMediaServer::Do_Node_Work, this, *itt)); t.join(); } } } } } _log.Log(LOG_STATUS, "Logitech Media Server: Worker stopped..."); }
void CPanasonic::Do_Work() { int scounter = 0; ReloadNodes(); while (!m_stoprequested) { if (scounter++ >= (m_iPollInterval * 2)) { boost::lock_guard<boost::mutex> l(m_mutex); scounter = 0; bool bWorkToDo = false; std::vector<boost::shared_ptr<CPanasonicNode> >::iterator itt; for (itt = m_pNodes.begin(); itt != m_pNodes.end(); ++itt) { if (!(*itt)->IsBusy()) { _log.Log(LOG_NORM, "Panasonic Plugin: (%s) - Restarting thread.", (*itt)->m_Name.c_str()); boost::thread* tAsync = new boost::thread(&CPanasonicNode::Do_Work, (*itt)); //m_ios.stop(); } if ((*itt)->IsOn()) bWorkToDo = true; } //if (bWorkToDo && m_ios.stopped()) // make sure that there is a boost thread to service i/o operations //{ // m_ios.reset(); // // Note that this is the only thread that handles async i/o so we don't // // need to worry about locking or concurrency issues when processing messages // _log.Log(LOG_NORM, "Panasonic Plugin: Restarting I/O service thread."); // boost::thread bt(boost::bind(&boost::asio::io_service::run, &m_ios)); //} } sleep_milliseconds(500); } UnloadNodes(); _log.Log(LOG_STATUS, "Panasonic Plugin: Worker stopped..."); }
void CDomoticzHardwareBase::Do_Heartbeat_Work() { int secCounter = 0; int hbCounter = 0; while (!m_stopHeartbeatrequested) { sleep_milliseconds(200); if (m_stopHeartbeatrequested) break; secCounter++; if (secCounter == 5) { secCounter = 0; hbCounter++; if (hbCounter % 12 == 0) { mytime(&m_LastHeartbeat); } } } }
void P1MeterSerial::Do_Work() { int secCounter = 0; while (!m_stoprequested) { sleep_milliseconds(200); if (m_stoprequested) break; secCounter++; if (secCounter == 5) { secCounter = 0; time_t atime = mytime(NULL); struct tm ltime; localtime_r(&atime, <ime); if (ltime.tm_sec % 12 == 0) { mytime(&m_LastHeartbeat); } } } }
bool CDavisLoggerSerial::StopHardware() { m_stoprequested=true; m_thread->join(); // Wait a while. The read thread might be reading. Adding this prevents a pointer error in the async serial class. sleep_milliseconds(10); if (isOpen()) { try { clearReadCallback(); close(); doClose(); setErrorStatus(true); } catch(...) { //Don't throw from a Stop command } } m_bIsStarted=false; return true; }
void CPhilipsHue::Do_Work() { int LastSecond=-1; _log.Log(LOG_STATUS,"Philips Hue: Worker started..."); while (!m_stoprequested) { sleep_milliseconds(500); time_t atime=mytime(NULL); int tsec = atime%HUE_POLL_INTERVAL; if (((tsec == 0) && ((atime%60) != LastSecond)) || (LastSecond == -1)) { LastSecond = (atime % 60); GetLightStates(); mytime(&m_LastHeartbeat); } } _log.Log(LOG_STATUS,"Philips Hue: Worker stopped..."); }
void P1MeterSerial::Do_Work() { int sec_counter = 0; int msec_counter = 0; while (!m_stoprequested) { sleep_milliseconds(200); if (m_stoprequested) break; msec_counter++; if (msec_counter == 5) { msec_counter = 0; sec_counter++; if (sec_counter % 12 == 0) { m_LastHeartbeat=mytime(NULL); } } } }
void udb_run(void) { uint16_t currentTime; uint16_t nextHeartbeatTime; if (strlen(SILSIM_SERIAL_RC_INPUT_DEVICE) == 0) { udb_pwIn[THROTTLE_INPUT_CHANNEL] = 2000; udb_pwTrim[THROTTLE_INPUT_CHANNEL] = 2000; } nextHeartbeatTime = get_current_milliseconds(); while (1) { if (!handleUDBSockets()) { sleep_milliseconds(1); } currentTime = get_current_milliseconds(); if (currentTime >= nextHeartbeatTime && !(nextHeartbeatTime <= UDB_STEP_TIME && currentTime >= UDB_WRAP_TIME-UDB_STEP_TIME)) { udb_callback_read_sensors(); udb_flags._.radio_on = (sil_radio_on && udb_pwIn[FAILSAFE_INPUT_CHANNEL] >= FAILSAFE_INPUT_MIN && udb_pwIn[FAILSAFE_INPUT_CHANNEL] <= FAILSAFE_INPUT_MAX); LED_GREEN = (udb_flags._.radio_on) ? LED_ON : LED_OFF ; if (udb_heartbeat_counter % 20 == 0) udb_background_callback_periodic(); // Run at 2Hz udb_servo_callback_prepare_outputs(); sil_ui_update(); if (udb_heartbeat_counter % 80 == 0) writeEEPROMFileIfNeeded(); // Run at 0.5Hz udb_heartbeat_counter++; nextHeartbeatTime = nextHeartbeatTime + UDB_STEP_TIME; if (nextHeartbeatTime > UDB_WRAP_TIME) nextHeartbeatTime -= UDB_WRAP_TIME; } process_queued_events(); } }
void CGpio::Do_Work() { int interruptNumber = NO_INTERRUPT; boost::posix_time::milliseconds duration(12000); std::vector<int> triggers; _log.Log(LOG_NORM,"GPIO: Worker started..."); while (!m_stoprequested) { #ifndef WIN32 boost::mutex::scoped_lock lock(interruptQueueMutex); if (!interruptCondition.timed_wait(lock, duration)) { //_log.Log(LOG_NORM, "GPIO: Updating heartbeat"); mytime(&m_LastHeartbeat); } else { while (!gpioInterruptQueue.empty()) { interruptNumber = gpioInterruptQueue.front(); triggers.push_back(interruptNumber); gpioInterruptQueue.erase(gpioInterruptQueue.begin()); _log.Log(LOG_NORM, "GPIO: Acknowledging interrupt for GPIO %d.", interruptNumber); } } lock.unlock(); if (m_stoprequested) { break; } while (!triggers.empty()) { interruptNumber = triggers.front(); triggers.erase(triggers.begin()); CGpio::ProcessInterrupt(interruptNumber); } #else sleep_milliseconds(100); #endif } _log.Log(LOG_NORM,"GPIO: Worker stopped..."); }