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.

service.hpp 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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. #ifdef WIN32
  35. int _tmain(int argc, TCHAR *argv[]);
  36. VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
  37. VOID WINAPI ServiceCtrlHandler(DWORD message);
  38. #else
  39. int main(int argc, char *argv[]);
  40. #endif
  41. namespace CodeDweller {
  42. /** Singleton class that implements a daemon (*nix) or service
  43. (Windows).
  44. This class implements a *nix daemon or a Windows service.
  45. To implement a daemon or service, implement the required methods
  46. of this class, and link with service.cpp. When compiled under
  47. *nix, the file service.cpp contains the definition of main for
  48. the *nix daemon. When compiled under Windows, the file
  49. service.cpp contains the entry points for the Windows service.
  50. Nomenclature:
  51. <ol>
  52. <li>Service is a *nix daemon or Windows service.</li>
  53. <li>Message is a posix signal or Windows message. This class
  54. supports the following messages:
  55. <ol>
  56. <li>Pause. This is the posix TSTP signal or Windows Pause
  57. message. This instructs the service to temporarily stop
  58. running.</li>
  59. <li>Resume. This is the posix CONT signal or Windows
  60. Resume message. This instructs the service to resume
  61. running after receiving a Pause message. If the service
  62. isn't temporarily stopped after receiving a Pause message,
  63. the Resume message has no effect.</li>
  64. <li>Stop. This is the posix TERM signal or Windows Stop
  65. message. This instructs the service to shut down and
  66. exit.</li>
  67. </ol>
  68. </li>
  69. <li>Callback. This is a function that is executed when a
  70. message is received.</li>
  71. </ol>
  72. */
  73. class Service
  74. {
  75. public:
  76. /// Callback functor interface.
  77. class Callback {
  78. public:
  79. /// Callback method.
  80. virtual void operator()() = 0;
  81. };
  82. /// Register a callback for receipt of Pause.
  83. //
  84. // \param[in] pauseFunctor is the function object to invoke when
  85. // Pause is received.
  86. //
  87. static void onPauseCall(Callback &pauseFunctor);
  88. /// Register a callback for receipt of Resume.
  89. //
  90. // \param[in] resumeFunctor is the function object to invoke when
  91. // Resume is received.
  92. //
  93. static void onResumeCall(Callback &resumeFunctor);
  94. /// Register a callback for receipt of Stop.
  95. //
  96. // \param[in] stopFunctor is the function object to invoke when
  97. // Stop is received.
  98. //
  99. static void onStopCall(Callback &stopFunctor);
  100. /// Check whether Pause was received.
  101. //
  102. // \returns if the Pause message was received, false otherwise.
  103. //
  104. static bool receivedPause();
  105. /// Check whether Resume was received.
  106. //
  107. // \returns if the Resume message was received, false otherwise.
  108. //
  109. static bool receivedResume();
  110. /// Check whether the last message received was Stop.
  111. //
  112. // \returns true if Stop was the most recent message received,
  113. // false otherwise.
  114. //
  115. static bool receivedStop();
  116. /// Clear receiving the Pause message.
  117. static void clearReceivedPause();
  118. /// Clear receiving the Resume message.
  119. static void clearReceivedResume();
  120. /// Clear receiving the Stop message.
  121. static void clearReceivedStop();
  122. /// Get a reference to the command-line arguments.
  123. //
  124. // \returns a reference to the vector of command-line arguments of
  125. // the application. Index i corresponds to command-line argument
  126. // i.
  127. //
  128. static const std::vector<std::string> &arguments();
  129. private:
  130. /// Private constructor prevents instantiation.
  131. Service();
  132. /// Prevent copying.
  133. Service(Service const&) {}
  134. /// Prevent assignment.
  135. void operator=(Service const&) {}
  136. /// Get the instance of the singleton.
  137. //
  138. // \returns a reference to the singleton.
  139. //
  140. static Service& getInstance();
  141. /// Main entry point.
  142. //
  143. // \param[in] argc is the number of arguments.
  144. //
  145. // \param[in] argv is an array of strings containing the
  146. // command-line arguments. The end of the array is indicated by a
  147. // null pointer.
  148. //
  149. // \returns exit code of the service.
  150. //
  151. int main(int argc, char *argv[]);
  152. #ifdef WIN32
  153. /// Service entry point for Windows.
  154. // \param[in] argc is the number of arguments.
  155. //
  156. // \param[in] argv is an array of strings containing the
  157. // command-line arguments. The end of the array is indicated by a
  158. // null pointer.
  159. //
  160. void serviceMain(DWORD argc, LPTSTR *argv);
  161. #endif
  162. /// Load the command-line arguments.
  163. //
  164. // This method loads the object with the command-line parameters.
  165. //
  166. // \param[in] argc is the number of arguments.
  167. //
  168. // \param[in] argv is an array of strings containing the
  169. // command-line arguments. The end of the array is indicated by a
  170. // null pointer.
  171. //
  172. void loadArguments(int argc, char *argv[]);
  173. /// Initialize and run the application.
  174. //
  175. // \returns the exit status of the service.
  176. //
  177. int run();
  178. /// Mutex to serialize access to the object.
  179. static std::mutex objectMutex;
  180. #ifdef WIN32
  181. /// Process a control message.
  182. //
  183. // \param[in] message is the message to process.
  184. //
  185. void processCtrlMessage(DWORD message);
  186. #else
  187. /// Thread start function to receive and process messages.
  188. void processMessages();
  189. #endif
  190. /// Command-line arguments.
  191. static std::vector<std::string> cmdLineArgs;
  192. /// True if Pause message was received.
  193. static bool pauseReceived;
  194. /// True if Resume message was received.
  195. static bool resumeReceived;
  196. /// True if Stop message was received.
  197. static bool stopReceived;
  198. /// Functions to invoke when the Pause is received.
  199. static std::vector<Callback *> pauseCallbacks;
  200. /// Functions to invoke when the Resume is received.
  201. static std::vector<Callback *> resumeCallbacks;
  202. /// Functions to invoke when the Stop is received.
  203. static std::vector<Callback *> stopCallbacks;
  204. #ifdef WIN32
  205. /// Status of the service.
  206. SERVICE_STATUS serviceStatus;
  207. /// Handle for accessing service status on the OS.
  208. SERVICE_STATUS_HANDLE serviceStatusHandle = NULL;
  209. friend int ::_tmain(int argc, TCHAR *argv[]);
  210. friend VOID WINAPI ::ServiceMain(DWORD argc, LPTSTR *argv);
  211. friend VOID WINAPI ::ServiceCtrlHandler(DWORD message);
  212. #else
  213. /// Set of signals to wait for.
  214. sigset_t signalSet;
  215. friend int ::main(int argc, char *argv[]);
  216. #endif
  217. };
  218. }
  219. #endif // SERVICE_HPP