Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

child.hpp 33KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. // \file child.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 child module provides classes to spawn and communicate
  24. with child processes.
  25. */
  26. #ifndef CHILD_HPP
  27. #define CHILD_HPP
  28. #ifdef _WIN32
  29. #include <windows.h>
  30. #endif
  31. #include <cstdint>
  32. #include <streambuf>
  33. #include <iostream>
  34. #include <string>
  35. #include <vector>
  36. #include <thread>
  37. #include <mutex>
  38. namespace CodeDweller {
  39. /**
  40. \namespace CodeDweller
  41. The CodeDweller namespace contains components providing high-level
  42. functionality for applications.
  43. */
  44. /** Class that abstracts the iostreams communication with a child
  45. process.
  46. This class provides functionality to create a child process,
  47. communicate with the child process via streams and signals, and
  48. obtain the exit code of the child process.
  49. */
  50. class ChildStream : public std::iostream {
  51. private:
  52. /// Streambuf class for reading from the standard output and
  53. /// writing to the standard input of the child process.
  54. class ChildStreambuf : public std::streambuf {
  55. friend class ChildStream;
  56. public:
  57. /// Constructor.
  58. //
  59. // \param[in] bufSize is the size in bytes of the input
  60. // buffer and output buffer.
  61. //
  62. explicit ChildStreambuf(std::size_t bufSize = 4096);
  63. #ifdef _WIN32
  64. /// Set the handle to read the standard output of the child
  65. /// process.
  66. //
  67. // \param[in] inHandle is the input handle for the standard
  68. // output of the child process.
  69. //
  70. void setInputHandle(HANDLE inHandle);
  71. /// Set the handle to write the standard input of the child
  72. /// process.
  73. //
  74. // \param[in] outHandle is the output handle for the standard
  75. // input of the child process.
  76. //
  77. void setOutputHandle(HANDLE outHandle);
  78. #else
  79. /// Set the file descriptor to read the standard output of the
  80. /// child process.
  81. //
  82. // \param[in] inFd is the input file descriptor for the standard
  83. // output of the child process.
  84. //
  85. void setInputFileDescriptor(int inFd);
  86. /// Set the file descriptor to write the standard input of the
  87. /// child process.
  88. //
  89. // \param[in] outFd is the output file descriptor for the
  90. // standard input of the child process.
  91. //
  92. void setOutputFileDescriptor(int outFd);
  93. #endif
  94. private:
  95. /** Return the number of bytes that can be read without
  96. blocking.
  97. This method checks if any input is available from the pipe,
  98. and returns the number of bytes in the input buffer plus 1.
  99. Reading that number of bytes will not block. Reading a
  100. larger number of bytes might block.
  101. \returns minimum number of bytes that can be read without
  102. blocking.
  103. */
  104. size_t numBytesAvailable() const;
  105. /// Override streambuf::underflow().
  106. int_type underflow();
  107. /// Flush the output buffer.
  108. void flushBuffer();
  109. /// Override streambuf::overflow().
  110. int_type overflow(int_type ch);
  111. /// Override streambuf::sync().
  112. int sync();
  113. /// Input and output handles.
  114. #ifdef _WIN32
  115. HANDLE inputHandle;
  116. HANDLE outputHandle;
  117. #else
  118. int inputFileDescriptor;
  119. int outputFileDescriptor;
  120. #endif
  121. /// Size of buffers.
  122. std::size_t bufferSize;
  123. /// Read buffer.
  124. std::vector<char> readBuffer;
  125. /// Write buffer.
  126. std::vector<char> writeBuffer;
  127. /// Copy constructor not implemented.
  128. ChildStreambuf(const ChildStreambuf &) = delete;
  129. /// Assignment operator not implemented.
  130. ChildStreambuf &operator=(const ChildStreambuf &) = delete;
  131. };
  132. /// Stream buffer for reading from the stdout and writing to the
  133. /// stdin of the child process.
  134. ChildStreambuf childStreambuf;
  135. public:
  136. /** Constructor for spawning with command-line parameters.
  137. The constructor configures the object, and spawns the child
  138. process.
  139. \param[in] args contains the child executable file name and
  140. command-line parameters. args[0] contains the full path of the
  141. executable, and args[1] thru args[n] are the command-line
  142. parameters.
  143. \param[in] bufSize is the input and output buffer size of the
  144. stream used to communicate with the child process.
  145. \throws runtime_error if an error occurs.
  146. */
  147. ChildStream(std::vector<std::string> const &args, size_t bufSize = 4096);
  148. /** Constructor for spawning without command-line parameters.
  149. The constructor configures the object, and spawns the child
  150. process.
  151. \param[in] childpath contains the child executable file name.
  152. \param[in] bufSize is the input and output buffer size of the
  153. stream used to communicate with the child process.
  154. \throws runtime_error if an error occurs.
  155. */
  156. ChildStream(std::string const &childpath, size_t bufSize = 4096);
  157. /** Constructor.
  158. The constructor configures the I/O buffers, but doesn't spawn
  159. any child process.
  160. \param[in] bufSize is the input and output buffer size of the
  161. stream used to communicate with the child process.
  162. */
  163. ChildStream(size_t bufSize = 4096);
  164. /** Destructor terminates the child process. */
  165. ~ChildStream();
  166. /** Spawn the child process.
  167. \param[in] args contains the child executable file name and
  168. command-line parameters. args[0] contains the full path of the
  169. executable, and args[1] thru args[n] are the command-line
  170. parameters.
  171. \throws runtime_error if an error occurs.
  172. \throws runtime_error if an error occurs.
  173. */
  174. void open(std::vector<std::string> const &args);
  175. /** Spawn the child process.
  176. \param[in] childpath contains the child executable file name.
  177. \throws runtime_error if an error occurs.
  178. */
  179. void open(std::string const &childpath);
  180. /** Get the number of bytes available for input.
  181. @returns number of bytes that can be read without blocking.
  182. */
  183. size_t numBytesAvailable() const;
  184. /** Check whether the child process is running.
  185. \returns True if the child process is running, false
  186. otherwise.
  187. */
  188. bool isRunning() const;
  189. /** Terminate the child process.
  190. \throws runtime_error if an error occurs.
  191. \throws logic_error if the child process is not running.
  192. */
  193. void close();
  194. /** Check whether the child process has exited.
  195. \returns True if the child process has exited, false
  196. otherwise.
  197. \throws runtime_error if an error occurs.
  198. \throws logic_error if the child process is not running.
  199. */
  200. bool isDone();
  201. /** Get the exit value of the child process.
  202. \returns The exit value of the child process if the child
  203. process has exited.
  204. \throws runtime_error if an error occurs.
  205. \throws logic_error if the child process has not exited.
  206. \throws logic_error if the child process is not running.
  207. */
  208. int32_t result();
  209. private:
  210. /** Spawn the child process.
  211. \throws runtime_error if an error occurs.
  212. */
  213. void run();
  214. /// Exit code to use when terminating the child process.
  215. static const uint32_t terminateExitCode = 0;
  216. /// True if the child process was successfully started.
  217. bool childStarted;
  218. /// True if the child process has exited.
  219. bool childExited;
  220. /// Initialize data members.
  221. void init();
  222. /// Child executable path and command-line parameters.
  223. std::vector<std::string> cmdArgs;
  224. #ifdef _WIN32
  225. /// Child's process handle.
  226. HANDLE childProcess;
  227. /// Child's thread handle.
  228. HANDLE childThread;
  229. #else
  230. /// Child process ID.
  231. pid_t childPid;
  232. #endif
  233. /// Exit value of the process.
  234. int32_t exitCode;
  235. /// True if the exit code has been obtained.
  236. bool exitCodeObtainedFlag;
  237. /// Return text for the most recent error.
  238. //
  239. // \returns Human-readable description of the most recent error.
  240. //
  241. static std::string getErrorText();
  242. };
  243. /** Class that abstracts the non-blocking communication with a child
  244. process.
  245. This class provides functionality to create a child process,
  246. communicate with the child process via non-blocking methods, and
  247. obtain the exit code of the child process.
  248. The existing process can be terminated by the close() method,
  249. and a new process spawned by the open() method.
  250. The close() method calls TerminateProcess under Windows, and
  251. sends SIGKILL under Linux. After sending SIGKILL, the close()
  252. methods calls waitpid() to wait for the child process to exit.
  253. When a child process is spawned, this class creates two threads:
  254. One for writing to the child, and one for reading from the
  255. child. These threads communicate with the user thread via:
  256. <ol>
  257. <li> A shared boolean that indicates when the threads should
  258. stop.</li>
  259. <li> A shared linear buffer containing data to write to the
  260. child process.</li>
  261. <li> A shared circular buffer containing data read from the
  262. child process.</li>
  263. </ol>
  264. */
  265. class Child {
  266. private:
  267. /** Circular buffer of characters. */
  268. class CircularBuffer {
  269. public:
  270. /** Constructor specifies the capacity.
  271. @param[in] maxSize is the capacity of the buffer.
  272. */
  273. CircularBuffer(size_t maxSize);
  274. /** Check whether the container is empty.
  275. @returns true if the container is empty, false otherwise.
  276. This method can be invoked by the user thread without
  277. serializing access to the object with a mutex. The
  278. reasoning is:
  279. 1) The buffer is empty if and only if iBegin == iEnd.
  280. 2) Only user thread modifies iBegin, by extracting data
  281. from the buffer.
  282. This means that if iBegin == iEnd, then:
  283. 1) iBegin is a valid index, since only the user thread can
  284. modify iBegin. The user thread maintains the validity
  285. of iBegin.
  286. 2) iEnd is a valid index, since it equals iBegin.
  287. 3) The result iBegin == iEnd is also valid, and indicates
  288. whether the buffer is empty.
  289. */
  290. bool empty() const;
  291. /** Get the size.
  292. @returns the number of bytes in the buffer.
  293. */
  294. size_t nUsed() const;
  295. /** Get the available space.
  296. @returns a number of bytes that can be written to the buffer
  297. without overwriting any existing data.
  298. This method can be invoked by the reader thread without
  299. serializing access to the object with a mutex. The reason
  300. is that:
  301. 1) The free space depends on capacity, iBegin, and iEnd.
  302. 2) The capacity is not changed while the threads are
  303. running, and only the reader thread modifies iEnd.
  304. Therefore, the reader thread always sees a valid and
  305. up-to-date value for capacity and iEnd.
  306. 3) Because the user thread modifies iBegin, iBegin might
  307. be invalid. The only invalid value is capacity + 1, in
  308. which case the correct value of iBegin is 0. This method
  309. checks for the invalid value, and uses the correct
  310. value as needed.
  311. 4) Because the user thread modifies iBegin, iBegin might
  312. be out-of-date. Because the user thread only
  313. increments iBegin, an out-of-date value would result in
  314. a smaller value of the available space in the buffer.
  315. */
  316. size_t nFree() const;
  317. /** Clear the buffer. */
  318. void clear();
  319. /** Put bytes to the buffer.
  320. @param[in] ptr is the address of the first byte to put.
  321. @param[in] nBytes is the number of bytes to put.
  322. @warning The capacity of the buffer must not be exceeded;
  323. exceeding the capacity corrupts the buffer.
  324. */
  325. void put(char const *ptr, size_t nBytes);
  326. /** Get bytes from the buffer.
  327. This method gets the specified number of bytes from the
  328. buffer, and erases those bytes from the buffer.
  329. The type T must have the following methods:
  330. <ol>
  331. <li>clear().</li>
  332. <li>capacity().</li>
  333. <li>reserve().</li>
  334. <li>push_back(char).</li>
  335. </ol>
  336. Both std::vector<char> and std::string can be used for T.
  337. @param[out] buf receives the data. The contents of buf are
  338. replaced with the data in the circular buffer.
  339. @param[in] nBytes is the number of bytes to get. Specifying
  340. a value of zero for nBytes gets and erases all the data.
  341. */
  342. template<typename T>
  343. void getAndErase(T &buf, size_t nBytes) {
  344. if ( (0 == nBytes) || (nBytes > nUsed()) ) {
  345. nBytes = nUsed();
  346. }
  347. buf.clear();
  348. if (buf.capacity() < nBytes) {
  349. buf.reserve(nBytes);
  350. }
  351. for (size_t i = 0; i < nBytes; i++) {
  352. buf.push_back(buffer[iBegin]);
  353. nextIndex(iBegin);
  354. }
  355. }
  356. /** Check whether specified data is present in the buffer.
  357. This method check whether the specified data is present in
  358. the buffer, and provides the number of characters before the
  359. specified data.
  360. The type U must have the following methods:
  361. <ol>
  362. <li>Methods required by CircularBuffer::match().</li>
  363. <li>size().</li>
  364. </ol>
  365. Both std::vector<char> and std::string can be used for T.
  366. @param[in] data is the specified data.
  367. @param[out] nBytesBefore is the number of bytes before the
  368. specified data.
  369. @returns true if the data is present in the buffer, false
  370. otherwise.
  371. @see CircularBuffer::match().
  372. */
  373. template<typename U>
  374. bool dataIsPresent(U const &data, size_t &nBytesBefore) const {
  375. size_t iLocalBegin = iBegin;
  376. if (nUsed() < data.size()) {
  377. return false;
  378. }
  379. size_t nToCheck = nUsed() - data.size() + 1;
  380. for (nBytesBefore = 0; nBytesBefore < nToCheck; nBytesBefore++) {
  381. if (match(data, iLocalBegin)) {
  382. return true;
  383. }
  384. nextIndex(iLocalBegin);
  385. }
  386. return false;
  387. }
  388. private:
  389. /** Increment the index.
  390. @param[in] index is the index to increment.
  391. */
  392. void nextIndex(size_t &index) const {
  393. index++;
  394. if (index >= capacity + 1)
  395. index = 0;
  396. }
  397. /** Check whether the specified data is in the buffer.
  398. This method checks whether the specified data is present in
  399. the buffer starting at the specified location.
  400. The type U must have the following methods:
  401. <ol>
  402. <li>operator[].</li>
  403. <li>size().</li>
  404. </ol>
  405. @param[in] data is the specified data.
  406. @param[in] index is the index of the buffer to start
  407. checking for the specified data.
  408. @returns true if the specified data is in the buffer, false
  409. otherwise.
  410. */
  411. template<typename U>
  412. bool match(U &data, size_t indx) const {
  413. for (size_t i = 0; i < data.size(); i++) {
  414. if (iEnd == indx) {
  415. return false;
  416. }
  417. if (data[i] != buffer[indx]) {
  418. return false;
  419. }
  420. nextIndex(indx);
  421. }
  422. return true;
  423. }
  424. /// Buffer to hold data.
  425. std::vector<char> buffer;
  426. /// Capacity of the buffer.
  427. size_t capacity;
  428. /// Index of first element.
  429. size_t iBegin;
  430. /// Index of one past the last element.
  431. size_t iEnd;
  432. };
  433. public:
  434. /** Constructor for spawning with command-line parameters.
  435. The constructor configures the object, and spawns the child
  436. process.
  437. \param[in] args contains the child executable file name and
  438. command-line parameters. args[0] contains the full path of the
  439. executable, and args[1] thru args[n] are the command-line
  440. parameters.
  441. \param[in] bufSize is the input and output buffer size of the
  442. stream used to communicate with the child process.
  443. \param[in] nominalAboveMinPollTime_ms is used to determine the
  444. minimum time in milliseconds that the writer thread sleeps
  445. when there's no data in the output buffer, and that the reader
  446. thread sleeps when there's no room in the input buffer. The
  447. minimum time is nominalAboveMinPollTime_ms +
  448. CodeDweller::MinimumSleeperTime.
  449. \param[in] deltaPollTime_ms is how much longer, in
  450. milliseconds, the maximum time to sleep is than the minimum time.
  451. \throws runtime_error if an error occurs.
  452. */
  453. Child(std::vector<std::string> const &args,
  454. size_t bufSize = 128 * 1024,
  455. std::uint16_t nominalAboveMinPollTime_ms = 0,
  456. std::uint16_t deltaPollTime_ms = 500);
  457. /** Constructor for spawning without command-line parameters.
  458. The constructor configures the object, and spawns the child
  459. process.
  460. \param[in] childpath contains the child executable file name.
  461. \param[in] bufSize is the input and output buffer size of the
  462. stream used to communicate with the child process.
  463. \param[in] nominalAboveMinPollTime_ms is used to determine the
  464. minimum time in milliseconds that the writer thread sleeps
  465. when there's no data in the output buffer, and that the reader
  466. thread sleeps when there's no room in the input buffer. The
  467. minimum time is nominalAboveMinPollTime_ms +
  468. CodeDweller::MinimumSleeperTime.
  469. \param[in] deltaPollTime_ms is how much longer, in
  470. milliseconds, the maximum time to sleep is than the minimum time.
  471. \throws runtime_error if an error occurs.
  472. */
  473. Child(std::string const &childpath,
  474. size_t bufSize = 128 * 1024,
  475. std::uint16_t nominalAboveMinPollTime_ms = 0,
  476. std::uint16_t deltaPollTime_ms = 500);
  477. /** Constructor.
  478. The constructor configures the I/O buffers, but doesn't spawn
  479. any child process.
  480. \param[in] bufSize is the input and output buffer size of the
  481. stream used to communicate with the child process.
  482. \param[in] nominalAboveMinPollTime_ms is used to determine the
  483. minimum time in milliseconds that the writer thread sleeps
  484. when there's no data in the output buffer, and that the reader
  485. thread sleeps when there's no room in the input buffer. The
  486. minimum time is nominalAboveMinPollTime_ms +
  487. CodeDweller::MinimumSleeperTime.
  488. \param[in] deltaPollTime_ms is how much longer, in
  489. milliseconds, the maximum time to sleep is than the minimum time.
  490. */
  491. Child(size_t bufSize = 4096,
  492. std::uint16_t nominalAboveMinPollTime_ms = 0,
  493. std::uint16_t deltaPollTime_ms = 500);
  494. /** Destructor terminates the child process. */
  495. ~Child();
  496. /** Spawn the child process.
  497. \param[in] args contains the child executable file name and
  498. command-line parameters. args[0] contains the full path of the
  499. executable, and args[1] thru args[n] are the command-line
  500. parameters.
  501. \throws runtime_error if an error occurs.
  502. \throws runtime_error if an error occurs.
  503. */
  504. void open(std::vector<std::string> const &args);
  505. /** Spawn the child process.
  506. \param[in] childpath contains the child executable file name.
  507. \throws runtime_error if an error occurs.
  508. */
  509. void open(std::string const &childpath);
  510. /** All-or-nothing non-blocking queue write request to the child.
  511. This methods attempts to queue a write request consisting of
  512. the entire contents of a container.
  513. The type T must have the following methods:
  514. <ol>
  515. <li>begin().</li>
  516. <li>end().</li>
  517. <li>size().</li>
  518. </ol>
  519. Both std::vector<char> and std::string can be used for T.
  520. @param[in] data is the data to queue.
  521. @returns true if the write request was queued, false
  522. otherwise.
  523. */
  524. template<typename T>
  525. bool write(T const &data) {
  526. if (!isRunning()) {
  527. throw std::logic_error("No child process is running.");
  528. }
  529. // The free space in the write buffer can be checked without
  530. // locking the mutex because:
  531. //
  532. // 1) bufferCapacity is unchanging, and
  533. //
  534. // 2) nWriteBytes is only decreased by the writer thread.
  535. //
  536. // This means that the calculated free space can only increase
  537. // by the action of the writer thread; the calculated free space
  538. // is a minimum value. In the worst case, this method would
  539. // return false unnecessarily.
  540. if (data.size() > bufferCapacity - nWriteBytes) {
  541. return false;
  542. }
  543. std::lock_guard<std::mutex> lock(writeBufferMutex);
  544. std::copy(data.begin(),
  545. data.end(),
  546. &(writeBuffer[nWriteBytes]));
  547. nWriteBytes += data.size();
  548. return true;
  549. }
  550. /** All-or-nothing non-blocking queue write request to the child.
  551. This methods attempts to queue a write request consisting of
  552. the entire contents of string literal.
  553. @param[in] data points to the string literal.
  554. @returns true if the write request was queued, false
  555. otherwise.
  556. */
  557. bool write(char const *data) {
  558. return write(std::string(data));
  559. }
  560. /** Non-blocking queue write request to the child.
  561. This methods attempts to queue a write request consisting of
  562. the the specified contents of a container. The number of
  563. bytes queued is the smaller of the size of the container and
  564. the number of free bytes in the output buffer.
  565. The type T must have the following methods:
  566. <ol>
  567. <li>begin().</li>
  568. <li>end().</li>
  569. <li>size().</li>
  570. </ol>
  571. Both std::vector<char> and std::string can be used for T.
  572. @param[in] data is the data to queue.
  573. @param[in] nBytes is the requested number of bytes to queue.
  574. @returns the number of bytes queued.
  575. */
  576. template<typename T>
  577. size_t write(T const &data, size_t nBytes) {
  578. if (!isRunning()) {
  579. throw std::logic_error("No child process is running.");
  580. }
  581. // See the comment above regarding checking the free space in the
  582. // write buffer without locking the mutex.
  583. size_t nFree = bufferCapacity - nWriteBytes;
  584. if (nBytes > nFree) {
  585. nBytes = nFree;
  586. }
  587. if (nBytes > data.size()) {
  588. nBytes = data.size();
  589. }
  590. std::lock_guard<std::mutex> lock(writeBufferMutex);
  591. std::copy(data.begin(),
  592. data.begin() + nBytes,
  593. &(writeBuffer[nWriteBytes]));
  594. nWriteBytes += nBytes;
  595. return nBytes;
  596. }
  597. /** Non-blocking queue write request to the child.
  598. This methods attempts to queue a write request consisting of
  599. as much as possible of the contents of the string.
  600. The type T must have the following methods:
  601. <ol>
  602. <li>begin().</li>
  603. <li>size().</li>
  604. </ol>
  605. Both std::vector<char> and std::string can be used for T.
  606. @param[in, out] data on input is the data to queue. On
  607. output, data contains the data that was not queued.
  608. @returns the number of bytes queued.
  609. */
  610. template<typename T>
  611. size_t writeAndShrink(T &data) {
  612. if (!isRunning()) {
  613. throw std::logic_error("No child process is running.");
  614. }
  615. // See the comment above regarding checking the free space in the
  616. // write buffer without locking the mutex.
  617. size_t nFree = bufferCapacity - nWriteBytes;
  618. if (0 == nFree) {
  619. return 0;
  620. }
  621. std::lock_guard<std::mutex> lock(writeBufferMutex);
  622. size_t nBytesToCopy = data.size();
  623. if (nBytesToCopy > nFree) {
  624. nBytesToCopy = nFree;
  625. }
  626. std::copy(data.begin(),
  627. data.begin() + nBytesToCopy,
  628. &(writeBuffer[nWriteBytes]));
  629. nWriteBytes += nBytesToCopy;
  630. data.erase(data.begin(), data.begin() + nBytesToCopy);
  631. return nBytesToCopy;
  632. }
  633. /** Check if all queued data was transmitted.
  634. @returns true if all the queued data was transmitted to the
  635. child, false otherwise.
  636. */
  637. bool isFinishedWriting() const;
  638. /** Non-blocking request to get data read from the child.
  639. This method attempts to get up to a specified number of bytes
  640. of data from the input buffer containing data received from
  641. the child. The data that is provided is erased from the input
  642. buffer.
  643. The type T must have the following methods:
  644. <ol>
  645. <li>Methods required by CircularBuffer::getAndErase().</li>
  646. <li>size().</li>
  647. </ol>
  648. Both std::vector<char> and std::string can be used for T.
  649. @param[out] data contains the copied data.
  650. @param[in] nBytes is the number of bytes to attempt to copy.
  651. If nBytes is zero, the contents of the entire input buffer is
  652. moved to data.
  653. @returns the number of bytes copied.
  654. @see CircularBuffer::getAndErase().
  655. */
  656. template<typename T>
  657. size_t read(T &data, size_t nBytes = 0) {
  658. if (!isRunning()) {
  659. throw std::logic_error("No child process is running.");
  660. }
  661. data.clear();
  662. // Can be called in the user thread without locking the mutex.
  663. if (readBuffer.empty()) {
  664. return 0;
  665. }
  666. std::lock_guard<std::mutex> lock(readBufferMutex);
  667. size_t nBytesToRead = nBytes;
  668. if (nBytesToRead > readBuffer.nUsed()) {
  669. nBytesToRead = readBuffer.nUsed();
  670. }
  671. readBuffer.getAndErase(data, nBytesToRead);
  672. return data.size();
  673. }
  674. /** Non-blocking request to get data up to a delimiter read from
  675. the child.
  676. This method check whether the specified delimiter is in the
  677. data received from the child.
  678. This method attempts to get data up to and not including a
  679. specified delimiter from the input buffer containing data
  680. received from the child. The data that is provided and the
  681. delimiter are erased from the input buffer.
  682. The type T must have the following methods:
  683. <ol>
  684. <li>Methods required by CircularBuffer::getAndErase().</li>
  685. <li>size().</li>
  686. <li>clear().</li>
  687. </ol>
  688. The type U must have the following methods:
  689. <ol>
  690. <li>Methods required by CircularBuffer::dataIsPresent().</li>
  691. <li>size().</li>
  692. <li>empty().</li>
  693. </ol>
  694. Both std::vector<char> and std::string can be used for T and U.
  695. @param[out] data contains the copied data.
  696. @param[in] delimiter contains the delimiter.
  697. @returns the number of bytes copied.
  698. @see CircularBuffer::getAndErase().
  699. @see CircularBuffer::dataIsPresent().
  700. */
  701. template<typename T, typename U>
  702. bool readDelimited(T &data, U const &delimiter) {
  703. if (!isRunning()) {
  704. throw std::logic_error("No child process is running.");
  705. }
  706. data.clear();
  707. // Can be called in the user thread without locking the mutex.
  708. if (readBuffer.empty()) {
  709. return false;
  710. }
  711. // Empty delimiter always matches.
  712. if (delimiter.empty()) {
  713. return true;
  714. }
  715. std::lock_guard<std::mutex> lock(readBufferMutex);
  716. size_t nBytesToRead;
  717. // Check for the presence of the delimiter.
  718. if (!readBuffer.dataIsPresent(delimiter, nBytesToRead)) {
  719. return false;
  720. }
  721. // Read the data.
  722. if (nBytesToRead > 0) {
  723. readBuffer.getAndErase(data, nBytesToRead);
  724. }
  725. // Discard the delimiter.
  726. T temp;
  727. readBuffer.getAndErase(temp, delimiter.size());
  728. return true;
  729. }
  730. /** Non-blocking request to get data up to a delimiter read from
  731. the child.
  732. This method check whether the specified delimiter is in the
  733. data received from the child.
  734. This method attempts to get data up to and not including a
  735. specified delimiter from the input buffer containing data
  736. received from the child. The data that is provided and the
  737. delimiter are erased from the input buffer.
  738. The type T must have the following methods:
  739. <ol>
  740. <li>Methods required by CircularBuffer::getAndErase().</li>
  741. <li>size().</li>
  742. <li>clear().</li>
  743. </ol>
  744. Both std::vector<char> and std::string can be used for T.
  745. @param[out] data contains the copied data.
  746. @param[in] delimiter contains the delimiter.
  747. @returns the number of bytes copied.
  748. @see CircularBuffer::getAndErase().
  749. */
  750. template<typename T>
  751. bool readDelimited(T &data, char const *delimiter) {
  752. return readDelimited(data, std::string(delimiter));
  753. }
  754. /** Check whether the child process is running.
  755. \returns True if the child process is running, false
  756. otherwise.
  757. */
  758. bool isRunning() const;
  759. /** Check error status.
  760. This method checks whether an error occurred when
  761. communicating with the child process.
  762. \param[out] errorDescription contains the description of any
  763. error that occurred.
  764. \returns true if an error occurred, false otherwise.
  765. */
  766. bool errorOccurred(std::string &errorDescription) const;
  767. /** Close the connection.
  768. This method terminate the child process if it is running, and
  769. resets the object. After this method is invoked, open() can
  770. be invoked to spawn and communicate with another child
  771. process.
  772. \throws runtime_error if an error occurs.
  773. \throws logic_error if the child process is not running.
  774. */
  775. void close();
  776. /** Check whether the child process has exited.
  777. \returns True if the child process has exited, false
  778. otherwise.
  779. \throws runtime_error if an error occurs.
  780. \throws logic_error if the child process is not running.
  781. */
  782. bool isDone();
  783. /** Get the exit value of the child process.
  784. \returns The exit value of the child process if the child
  785. process has exited.
  786. \throws runtime_error if an error occurs.
  787. \throws logic_error if the child process has not exited.
  788. \throws logic_error if the child process is not running.
  789. */
  790. int32_t result();
  791. private:
  792. /// Initialize data members.
  793. void init();
  794. /** Spawn the child process.
  795. \throws runtime_error if an error occurs.
  796. */
  797. void run();
  798. /// Reader thread object.
  799. std::thread readerThread;
  800. /// Thread start function to read data from the child.
  801. void readFromChild();
  802. /// Writer thread object.
  803. std::thread writerThread;
  804. /// Thread start function to send data to the child.
  805. void writeToChild();
  806. /// True if readerThread and writerThread are to stop.
  807. bool stopFlag;
  808. /// True if both the reader and writer the writer threads are
  809. /// running, false otherwise.
  810. bool threadsAreRunning;
  811. /// Description of any error.
  812. std::string errorText;
  813. /// Input and output handles.
  814. #ifdef _WIN32
  815. HANDLE inputHandle;
  816. HANDLE outputHandle;
  817. #else
  818. int inputFileDescriptor;
  819. int outputFileDescriptor;
  820. #endif
  821. /// Capacity of buffers.
  822. std::size_t bufferCapacity;
  823. /// Read buffer.
  824. CircularBuffer readBuffer;
  825. /// Mutex to serialize access to readBuffer.
  826. std::mutex readBufferMutex;
  827. /// Write buffer.
  828. std::vector<char> writeBuffer;
  829. /// Number of bytes in writeBuffer.
  830. size_t nWriteBytes;
  831. /// Mutex to serialize access to writeBuffer.
  832. std::mutex writeBufferMutex;
  833. /// Number of bytes in writer thread transmit buffer.
  834. size_t nTransmitBytes;
  835. /// Nominal poll time.
  836. //
  837. // If there isn't room in readBuffer, readerThread aperiodically
  838. // checks whether room is available. The check times are
  839. // determined by a CodeDweller::PollTimer object, which requires a
  840. // nominal poll time and a maximum poll time.
  841. int nominalPollTime_ms;
  842. /// Maximum poll time.
  843. int maximumPollTime_ms;
  844. /// Exit code to use when terminating the child process.
  845. static const uint32_t terminateExitCode = 0;
  846. /// True if the child process was successfully started.
  847. bool childStarted;
  848. /// True if the child process has exited.
  849. bool childExited;
  850. /// Child executable path and command-line parameters.
  851. std::vector<std::string> cmdArgs;
  852. #ifdef _WIN32
  853. /// Child's process handle.
  854. HANDLE childProcess;
  855. /// Child's thread handle.
  856. HANDLE childThread;
  857. #else
  858. /// Child process ID.
  859. pid_t childPid;
  860. #endif
  861. /// Exit value of the process.
  862. int32_t exitCode;
  863. /// True if the exit code has been obtained.
  864. bool exitCodeObtainedFlag;
  865. /// Return text for the most recent error.
  866. //
  867. // \returns Human-readable description of the most recent error.
  868. //
  869. static std::string getErrorText();
  870. };
  871. }
  872. #endif // CHILD_HPP