// \file serviceProgram.cpp // // Service program for testing CodeDweller::Service. // // Usage: // // serviceProgram // // where is the name of a file to write to, and // is the message callback timeout to test. can // be Pause, Resume, or Stop. If is anything else, then // is ignored. // // This program: // // 1) Sets the callback timeout to 500 ms. // // 2) Registers callbacks for various messages. Each callback // normaly sleeps for 400 ms, which is less than the timeout. // However, if is present, the callback for the specified // message sleeps for 600 ms. This should cause the service to // exit. // // 3) While the stop flag is false, outputs the status of all flags // to the log file every 2 seconds, and clears all flags. // // 4) After Stop is received, output the status of all flags, and // exit. // // Copyright (C) 2014 MicroNeil Research Corporation. // // This program is part of the MicroNeil Research Open Library Project. For // more information go to http://www.microneil.com/OpenLibrary/index.html // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your // option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program; if not, write to the Free Software Foundation, Inc., 59 Temple // Place, Suite 330, Boston, MA 02111-1307 USA //============================================================================== ///////////////////////////////////////////////////////////////////////////// // Configuration //////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // How long to sleep between iterations. This value is longer for // Windows because the sc command takes about 0.7 s to execute on the // development/text Windows 7 system. #ifdef WIN32 const int delayTime_ms = 2700; #else const int delayTime_ms = 2000; #endif // Callback timeout time. const int timeoutTime_ms = 500; // How long the callback takes to not exceed the timeout. const int shortSleepTime_ms = 400; // How long the callback takes to exceed the timeout. const int longSleepTime_ms = 600; ///////////////////////////////////////////////////////////////////////////// // End of configuration ///////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// #include #include #include #include "CodeDweller/service.hpp" /// Callback functor for Pause message. class PauseCallback : public CodeDweller::Service::Callback { public: PauseCallback() : pauseFlag(false) {} // Total sleep time for all Pause callbacks should be less than 1000 // ms. Reason: The while loop below sleeps for two seconds, and the // buildAndRun script sends the message one second into the sleep. // The callbacks must be completed before the main loop checks the // pauseFlag value. // // This applies to ResumeCallback and StopCallback. int sleepTime_ms = shortSleepTime_ms; bool pauseFlag; void operator()() { std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime_ms)); pauseFlag = true; } }; PauseCallback pauseCbck; PauseCallback pauseCbck1; /// Callback functor for Resume message. class ResumeCallback : public CodeDweller::Service::Callback { public: ResumeCallback() : resumeFlag(false) {} int sleepTime_ms = shortSleepTime_ms; bool resumeFlag; void operator()() { std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime_ms)); resumeFlag = true; } }; ResumeCallback resumeCbck; ResumeCallback resumeCbck1; /// Callback functor for Stop message. class StopCallback : public CodeDweller::Service::Callback { public: StopCallback() : stopFlag(false) {} int sleepTime_ms = shortSleepTime_ms; bool stopFlag; void operator()() { std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime_ms)); stopFlag = true; } }; StopCallback stopCbck; StopCallback stopCbck1; StopCallback notStopCbck; int CodeDweller::Service::run() { // Set the callback timeout to the default. CodeDweller::Service::setStopCallbackTimeout_ms(timeoutTime_ms); // Get the log file name. auto arguments = CodeDweller::Service::arguments(); if (arguments.size() == 3) { // Increase the time it takes for a callback to execute. if (arguments[2] == "Pause") { pauseCbck.sleepTime_ms = longSleepTime_ms; pauseCbck1.sleepTime_ms = longSleepTime_ms; } else if (arguments[2] == "Resume") { resumeCbck.sleepTime_ms = longSleepTime_ms; resumeCbck1.sleepTime_ms = longSleepTime_ms; } else if (arguments[2] == "Stop") { stopCbck.sleepTime_ms = longSleepTime_ms; stopCbck1.sleepTime_ms = longSleepTime_ms; } } if ( (arguments.size() != 2) && (arguments.size() != 3) ) { return(EXIT_FAILURE); } // Get log file. std::ofstream logStream(arguments[1], std::fstream::app); // Register the callbacks. CodeDweller::Service::onPauseCall(pauseCbck); CodeDweller::Service::onPauseCall(pauseCbck1); CodeDweller::Service::onResumeCall(resumeCbck); CodeDweller::Service::onResumeCall(resumeCbck1); CodeDweller::Service::onStopCall(stopCbck); CodeDweller::Service::onStopCall(stopCbck1); while (!stopCbck.stopFlag) { logStream << "Sleeping 2 s..."; logStream.flush(); std::this_thread::sleep_for(std::chrono::milliseconds(delayTime_ms)); logStream << "done." << std::endl; logStream << "receivedPause(): " << CodeDweller::Service::receivedPause() << std::endl; logStream << "receivedResume(): " << CodeDweller::Service::receivedResume() << std::endl; logStream << "receivedStop(): " << CodeDweller::Service::receivedStop() << std::endl; logStream << "Clearing all flags." << std::endl; CodeDweller::Service::clearReceivedPause(); CodeDweller::Service::clearReceivedResume(); CodeDweller::Service::clearReceivedStop(); logStream << "receivedPause(): " << CodeDweller::Service::receivedPause() << std::endl; logStream << "receivedResume(): " << CodeDweller::Service::receivedResume() << std::endl; logStream << "receivedStop(): " << CodeDweller::Service::receivedStop() << std::endl; logStream << "pauseCbck.pauseFlag: " << pauseCbck.pauseFlag << std::endl; logStream << "pauseCbck1.pauseFlag: " << pauseCbck1.pauseFlag << std::endl; logStream << "resumeCbck.resumeFlag: " << resumeCbck.resumeFlag << std::endl; logStream << "resumeCbck1.resumeFlag: " << resumeCbck1.resumeFlag << std::endl; logStream << "stopCbck.stopFlag: " << stopCbck.stopFlag << std::endl; logStream << "stopCbck1.stopFlag: " << stopCbck1.stopFlag << std::endl; logStream << "notStopCbck.stopFlag: " << notStopCbck.stopFlag << std::endl; pauseCbck.pauseFlag = false; pauseCbck1.pauseFlag = false; resumeCbck.resumeFlag = false; resumeCbck1.resumeFlag = false; logStream << std::endl; } logStream << "Exiting." << std::endl; logStream.close(); return(EXIT_SUCCESS); }