You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // \file service.hpp
  2. //
  3. // Copyright (C) 2014 MicroNeil Research Corporation.
  4. //
  5. // This program is part of the MicroNeil Research Open Library Project. For
  6. // more information go to http://www.microneil.com/OpenLibrary/index.html
  7. //
  8. // This program is free software; you can redistribute it and/or modify it
  9. // under the terms of the GNU General Public License as published by the
  10. // Free Software Foundation; either version 2 of the License, or (at your
  11. // option) any later version.
  12. //
  13. // This program is distributed in the hope that it will be useful, but WITHOUT
  14. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  16. // more details.
  17. //
  18. // You should have received a copy of the GNU General Public License along with
  19. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  20. // Place, Suite 330, Boston, MA 02111-1307 USA
  21. //==============================================================================
  22. /*
  23. \brief The service module provides a framework for implementing *nix
  24. daemons and Windows services.
  25. */
  26. #ifndef SERVICE_HPP
  27. #define SERVICE_HPP
  28. #ifdef WIN32
  29. #include <windows.h>
  30. #endif
  31. #include <string>
  32. #include <vector>
  33. #include <mutex>
  34. namespace CodeDweller {
  35. /** Singleton class that implements a daemon (*nix) or service
  36. (Windows).
  37. This class implements a *nix daemon or a Windows service.
  38. To implement a daemon or service, implement the required methods
  39. of this class, and link with service.cpp. When compiled under
  40. *nix, the file service.cpp contains the definition of main for
  41. the *nix daemon. When compiled under Windows, the file
  42. service.cpp contains the entry points for the Windows service.
  43. Nomenclature:
  44. <ol>
  45. <li>Service is a *nix daemon or Windows service.</li>
  46. <li>Message is a posix signal or Windows message. This class
  47. supports the following messages:
  48. <ol>
  49. <li>Pause. This is the posix TSTP signal or Windows Pause
  50. message. This instructs the service to temporarily stop
  51. running.</li>
  52. <li>Resume. This is the posix CONT signal or Windows
  53. Resume message. This instructs the service to resume
  54. running after receiving a Pause message. If the service
  55. isn't temporarily stopped after receiving a Pause message,
  56. the Resume message has no effect.</li>
  57. <li>Stop. This is the posix TERM signal or Windows Stop
  58. message. This instructs the service to shut down and
  59. exit.</li>
  60. </ol>
  61. </li>
  62. <li>Callback. This is a function that is executed when a
  63. message is received.</li>
  64. </ol>
  65. */
  66. class Service
  67. {
  68. public:
  69. /// Get the instance of the singleton.
  70. //
  71. // \returns a reference to the singleton.
  72. //
  73. static Service& getInstance();
  74. /// Callback functor interface.
  75. class Callback {
  76. public:
  77. /// Callback method.
  78. virtual void operator()() = 0;
  79. };
  80. /// Main entry point.
  81. //
  82. // \param[in] argc is the number of arguments.
  83. //
  84. // \param[in] argv is an array of strings containing the
  85. // command-line arguments. The end of the array is indicated by a
  86. // null pointer.
  87. //
  88. // \returns exit code of the service.
  89. //
  90. int main(int argc, char *argv[]);
  91. #ifdef WIN32
  92. /// Service entry point for Windows.
  93. // \param[in] argc is the number of arguments.
  94. //
  95. // \param[in] argv is an array of strings containing the
  96. // command-line arguments. The end of the array is indicated by a
  97. // null pointer.
  98. //
  99. void serviceMain(DWORD argc, LPTSTR *argv);
  100. #endif
  101. /// Register a callback for receipt of Pause.
  102. //
  103. // \param[in] pauseFunctor is the function object to invoke when
  104. // Pause is received.
  105. //
  106. void onPauseCall(Callback &pauseFunctor);
  107. /// Register a callback for receipt of Resume.
  108. //
  109. // \param[in] resumeFunctor is the function object to invoke when
  110. // Resume is received.
  111. //
  112. void onResumeCall(Callback &resumeFunctor);
  113. /// Register a callback for receipt of Stop.
  114. //
  115. // \param[in] stopFunctor is the function object to invoke when
  116. // Stop is received.
  117. //
  118. void onStopCall(Callback &stopFunctor);
  119. /// Check whether Pause was received.
  120. //
  121. // \returns if the Pause message was received, false otherwise.
  122. //
  123. bool receivedPause();
  124. /// Check whether Resume was received.
  125. //
  126. // \returns if the Resume message was received, false otherwise.
  127. //
  128. bool receivedResume();
  129. /// Check whether the last message received was Stop.
  130. //
  131. // \returns true if Stop was the most recent message received,
  132. // false otherwise.
  133. //
  134. bool receivedStop();
  135. /// Clear receiving the Pause message.
  136. void clearReceivedPause();
  137. /// Clear receiving the Resume message.
  138. void clearReceivedResume();
  139. /// Clear receiving the Stop message.
  140. void clearReceivedStop();
  141. /// Get a reference to the command-line arguments.
  142. //
  143. // \returns a reference to the vector of command-line arguments of
  144. // the application. Index i corresponds to command-line argument
  145. // i.
  146. //
  147. const std::vector<std::string> &arguments();
  148. private:
  149. /// Private constructor prevents instantiation.
  150. Service();
  151. /// Prevent copying.
  152. Service(Service const&) {}
  153. /// Prevent assignment.
  154. void operator=(Service const&) {}
  155. public:
  156. /// Load the command-line arguments.
  157. //
  158. // This method loads the object with the command-line parameters.
  159. //
  160. // \param[in] argc is the number of arguments.
  161. //
  162. // \param[in] argv is an array of strings containing the
  163. // command-line arguments. The end of the array is indicated by a
  164. // null pointer.
  165. //
  166. void loadArguments(int argc, char *argv[]);
  167. /// Initialize and run the application.
  168. //
  169. // \returns the exit status of the service.
  170. //
  171. int run();
  172. private:
  173. /// Mutex to serialize access to the object.
  174. static std::mutex objectMutex;
  175. #ifdef WIN32
  176. public:
  177. /// Process messages.
  178. //
  179. // \param[in] message is the message to process.
  180. //
  181. void processMessages(DWORD message);
  182. private:
  183. #else
  184. /// Thread start function to receive and process messages.
  185. void processMessages();
  186. #endif
  187. /// Command-line arguments.
  188. std::vector<std::string> cmdLineArgs;
  189. /// True if Pause message was received.
  190. bool pauseReceived;
  191. /// True if Resume message was received.
  192. bool resumeReceived;
  193. /// True if Stop message was received.
  194. bool stopReceived;
  195. /// Functions to invoke when the Pause is received.
  196. std::vector<Callback *> pauseCallbacks;
  197. /// Functions to invoke when the Resume is received.
  198. std::vector<Callback *> resumeCallbacks;
  199. /// Functions to invoke when the Stop is received.
  200. std::vector<Callback *> stopCallbacks;
  201. #ifdef WIN32
  202. /// Name of service.
  203. std::string serviceName;
  204. /// Status of the service.
  205. SERVICE_STATUS serviceStatus;
  206. /// Handle for accessing service status on the OS.
  207. SERVICE_STATUS_HANDLE serviceStatusHandle = NULL;
  208. #else
  209. /// Set of signals to wait for.
  210. sigset_t signalSet;
  211. #endif
  212. };
  213. }
  214. #endif // SERVICE_HPP