BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balb_pipetaskmanager.h
Go to the documentation of this file.
1/// @file balb_pipetaskmanager.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balb_pipetaskmanager.h -*-C++-*-
8#ifndef INCLUDED_BALB_PIPETASKMANAGER
9#define INCLUDED_BALB_PIPETASKMANAGER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balb_pipetaskmanager balb_pipetaskmanager
15/// @brief Provide a pipe-based mechanism to process task control messages.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balb
19/// @{
20/// @addtogroup balb_pipetaskmanager
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balb_pipetaskmanager-purpose"> Purpose</a>
25/// * <a href="#balb_pipetaskmanager-classes"> Classes </a>
26/// * <a href="#balb_pipetaskmanager-description"> Description </a>
27/// * <a href="#balb_pipetaskmanager-configuring-the-balb-pipetaskmanager"> Configuring the balb::PipeTaskManager </a>
28/// * <a href="#balb_pipetaskmanager-thread-safety"> Thread Safety </a>
29/// * <a href="#balb_pipetaskmanager-requirements-for-the-named-pipe"> Requirements for the Named Pipe </a>
30/// * <a href="#balb_pipetaskmanager-message-requirements"> Message Requirements </a>
31/// * <a href="#balb_pipetaskmanager-pipe-atomicity"> Pipe Atomicity </a>
32/// * <a href="#balb_pipetaskmanager-usage"> Usage </a>
33/// * <a href="#balb_pipetaskmanager-example-1-basic-usage"> Example 1: Basic Usage </a>
34///
35/// # Purpose {#balb_pipetaskmanager-purpose}
36/// Provide a pipe-based mechanism to process task control messages.
37///
38/// # Classes {#balb_pipetaskmanager-classes}
39///
40/// - balb::PipeTaskManager: message-to-handler dispatcher
41///
42/// @see balb_controlmanager, balb_pipecontrolchannel
43///
44/// # Description {#balb_pipetaskmanager-description}
45/// This component provides a mechanism, `balb::PipeTaskManager`,
46/// that listens on a named pipe for messages that are typically used to
47/// influence the behavior of a (running) task.
48///
49/// For example, a `balb::PipeTaskManager` might be configured to listen on a
50/// well known named pipe (e.g., `myapplication.ctrl`), for the control messages
51/// starting with:
52/// * "EXIT",
53/// * "RESTART",
54/// * "LOG", and
55/// * "HELP".
56///
57/// The use of imperative verbs for the first field of a message is a common
58/// practice. The first field is called the message "prefix". On receipt of a
59/// message with a known prefix, a previously registered handler functor is
60/// invoked with two arguments:
61/// 1. the prefix value, and
62/// 2. an `bsl::istream` from which the rest of the message (if any) can be
63/// read.
64/// Thus, we have a mechanism by which a running task can be sent commands and,
65/// optionally, arguments for those commands.
66///
67/// Once the relationship between `prefix` and handler has been specified, the
68/// `start` method is used to create the named pipe (or re-open an existing
69/// named pipe) and a thread created to listen for messages.
70///
71/// A human user on a console might then use a command line application to send
72/// control messages to the `myapplication.ctrl` pipe to configure the behavior
73/// of the running task. In the example above, the handler for the `LOG` prefix
74/// expects additional parameters. Thus:
75/// @code
76/// echo "LOG VERBOSITY 4" > $SOCKDIR/myapplication.ctrl
77/// @endcode
78/// changes the logging verbosity of the task to level "4". See
79/// @ref bdls_pipeutil for functions that can be invoked from C++ code to send
80/// messages to a named pipe.
81///
82/// ## Configuring the balb::PipeTaskManager {#balb_pipetaskmanager-configuring-the-balb-pipetaskmanager}
83///
84///
85/// A default constructed `balb::PipeTaskManager` has no registered handlers.
86/// Users can use the exposed `balb::ControlManager`, to register different
87/// control message prefixes (typically "verbs") to dispatch received messages
88/// to an appropriate functor.
89///
90/// Alternatively, one can construct a `balb::PipeTaskManager` using a
91/// separately created and configured a `balb::ControlManager` object. Doing so
92/// allows that single `balb::ControlManager` to be shared among several
93/// `balb::PipeTaskManager` objects, each listening on a different named pipe.
94///
95/// ## Thread Safety {#balb_pipetaskmanager-thread-safety}
96///
97///
98/// This component is thread-safe but not thread-enabled, meaning that multiple
99/// threads may safely use their own instances of `balb::PipeTaskManager`, but
100/// may not manipulate the same instance of `balb::PipeTaskManager`
101/// simultaneously. Note that the contained `balb::ControlManager` object is
102/// available via both `const` and non=`const` references and that object *is*
103/// safe for multiple threads.
104///
105/// ## Requirements for the Named Pipe {#balb_pipetaskmanager-requirements-for-the-named-pipe}
106///
107///
108/// The `balb::PipeTaskManger` objects waits for messages from a named pipe
109/// provided to the `start` method. The argument to `start` -- mapped to all
110/// lower case, if needed -- determines the basename of the named pipe. The
111/// directory of that named pipe depends on the platform and environment
112/// variables.
113///
114/// * On Windows, that directory is: ``\\.\pipe\``.
115///
116/// * On Unix systems, that directory is determined by
117/// - the `SOCKDIR` environment variable, if set; otherwise,
118/// - the `TMPDIR` environment variable, if set; otherwise,
119/// - the current directory.
120///
121/// See the `makeCanonicalName` overloads in @ref bdls_pipeutil for details.
122///
123/// Moreover, the `start` method must be able to *freshly* create a named pipe.
124/// In general, `start` will fail if a named pipe of the calculated canonical
125/// name already exists. On Unix, if that named pipe is not in use (not open
126/// for reading), the `start` attempts to remove and re-create that named pipe.
127///
128/// On Unix systems, named pipes are created having the permission `0666` (read
129/// and write for user, group, and other) limited by the current `umask` value
130/// of the process.
131///
132/// On successful completion of `start`, the (full) pathname of the created
133/// named pipe is provided by the `pipeName` accessor. The full path name must
134/// be passed to sending processes so they can open that named pipe and write
135/// control messages.
136///
137/// ## Message Requirements {#balb_pipetaskmanager-message-requirements}
138///
139///
140/// Each message consists of a sequence of fields separated by blanks and/or
141/// tabs and terminated by a newline (``\n``) character. The terminating
142/// newline is not passed to the message handler.
143///
144/// The first field is called the message "prefix" and is used to find a
145/// previously registered handler for the message. The handler lookup is case
146/// insensitive. Empty messages (newline only) and messages for which no
147/// handler can be found are silently ignored.
148///
149/// Note that this facility provides a one-way flow of information from the
150/// writer to a named pipe to the registered message handler. There is no
151/// mechanism here for validating message (e.g., a given prefix has required
152/// additional fields) or returning status. Many applications provide output by
153/// writing to the console or to a log.
154///
155/// ### Pipe Atomicity {#balb_pipetaskmanager-pipe-atomicity}
156///
157///
158/// Users that expect multiple concurrent writers to a single pipe must be aware
159/// that the message content might be corrupted (interleaved) unless:
160///
161/// 1. Each message is written to the pipe in a single `write` system call.
162/// 2. The length of each message is less than `PIPE_BUF` (the limit for
163/// guaranteed atomicity).
164///
165/// The value `PIPE_BUF` depends on the platform:
166/// @code
167/// +------------------------------+------------------+
168/// | Platform | PIPE_BUF (bytes) |
169/// +------------------------------+------------------+
170/// | POSIX (minimum requirement)) | 512 |
171/// | IBM | 32,768 |
172/// | SUN | 32,768 |
173/// | Linux | 65,536 |
174/// | Windows | 65,536 |
175/// +------------------------------+------------------+
176/// @endcode
177/// Also note that Linux allows the `PIPE_BUF` size to be changed via the
178/// `fcntl` system call.
179///
180/// ## Usage {#balb_pipetaskmanager-usage}
181///
182///
183/// This section illustrates intended use of this component.
184///
185/// ### Example 1: Basic Usage {#balb_pipetaskmanager-example-1-basic-usage}
186///
187///
188/// Suppose one is creating an application that allows for dynamically changing
189/// its logging verbosity level, resetting to its initial state, to shutdown
190/// cleanly, and the listing a description of supported messages.
191///
192/// The `balb::PipeTaskManager` class can be used to provide support for
193/// messages that are sent via a named pipe and have the syntax shown below:
194/// @code
195/// This process responds to the following messages:
196/// EXIT no arguments
197/// Terminate the application.
198/// HELP
199/// Display this message
200/// LOG <GET|SET <level> >
201/// Get/set verbosity level.
202/// RESTART no arguments
203/// Restart the application.
204/// @endcode
205/// Note that the above description corresponds to the output produced by our
206/// application in response to a "HELP" message.
207///
208/// First, define several global, atomic variables that will be used to exchange
209/// information between the thread that monitors the named pipe and the other
210/// threads of the application.
211/// @code
212/// static bsls::AtomicBool done(false);
213/// static bsls::AtomicInt progress(0);
214/// static bsls::AtomicInt myLoggingManagerLevel(0);
215/// @endcode
216/// Then, we define helper functions `myLoggingManagerGet` and
217/// `myLoggingManagerSet` so that the handler for "LOG" messages can delegate
218/// processing the "GET" and "SET" subcommands. The other defined messages have
219/// minimal syntax so use of a delegation pattern is overkill in those cases.
220/// @code
221/// /// Print the current log level to the console.
222/// void myLoggingManagerGet()
223/// {
224/// bsl::cout << "LOG LEVEL IS NOW" << ": "
225/// << myLoggingManagerLevel << bsl::endl;
226/// }
227///
228/// /// Set the log level to the value obtained from the specified
229/// /// `message` and print that value to the console.
230/// void myLoggingManagerSet(bsl::istream& message)
231/// {
232/// int newLogLevel;
233/// message >> newLogLevel; // Cannot stream to an `bsls::AtomicInt`.
234///
235/// myLoggingManagerLevel = newLogLevel;
236///
237/// bsl::cout << "LOG LEVEL SET TO" << ": "
238/// << myLoggingManagerLevel << bsl::endl;
239/// }
240/// @endcode
241/// Next, define handler functions for the "EXIT", "RESTART", and "LOG"
242/// messages.
243/// @code
244/// /// Handle a "EXIT" message.
245/// void onExit(const bsl::string_view& , bsl::istream& )
246/// {
247/// bsl::cout << "onExit" << bsl::endl;
248/// done = true;
249/// }
250///
251/// /// Handle a "RESTART" message.
252/// void onRestart(const bsl::string_view& , bsl::istream& )
253/// {
254/// bsl::cout << "onRestart" << bsl::endl;
255/// progress = 0;
256/// }
257///
258/// /// Handle a "LOG" message supporting sub command "GET" and "SET". If
259/// /// the subcommand is "SET" the new log level is obtained from the
260/// /// specified `message`.
261/// void onLog(const bsl::string_view& , bsl::istream& message)
262/// {
263/// bsl::cout << "onLog" << bsl::endl;
264///
265/// bsl::string subCommand;
266/// message >> subCommand;
267/// // See the registration of the 'onLog' handler below for the
268/// // details of the supported sub commands and their arguments.
269///
270/// if ("GET" == subCommand) {
271/// myLoggingManagerGet();
272/// }
273/// else if ("SET" == subCommand) {
274/// myLoggingManagerSet(message);
275/// }
276/// else {
277/// bsl::cout << "onLog" << ": "
278/// << "unknown subcommand" << ": "
279/// << subCommand << bsl::endl;
280/// }
281/// }
282/// @endcode
283/// Notice that no handler is yet defined for the "HELP" message. That
284/// functionally can be provided using methods of the contained
285/// `balb::ControlManager` object. See below.
286///
287/// Then, create a `balb::PipeTaskManger` object and register the above
288/// functions as handlers:
289/// @code
290/// /// Run Application1 and return status.
291/// int myApplication1()
292/// {
293/// balb::PipeTaskManager taskManager;
294///
295/// int rc;
296///
297/// rc = taskManager.controlManager().registerHandler(
298/// "EXIT",
299/// "no arguments",
300/// "Terminate the application.",
301/// onExit);
302/// assert(0 == rc);
303/// rc = taskManager.controlManager().registerHandler(
304/// "RESTART",
305/// "no arguments",
306/// "Restart the application.",
307/// onRestart);
308/// assert(0 == rc);
309/// rc = taskManager.controlManager().registerHandler(
310/// "LOG",
311/// "<GET|SET <level> >",
312/// "Get/set verbosity level.",
313/// onLog);
314/// assert(0 == rc);
315/// @endcode
316/// and add an additional handler that provides a list of the registered
317/// messages and the syntax for using them:
318/// @code
319/// rc = taskManager.controlManager().registerUsageHandler(bsl::cout);
320/// assert(0 == rc);
321/// @endcode
322/// Next, if we are on a Unix system, we confirm that our named pipes will be
323/// created in the directory named by the `TMPDIR` environment variable:
324/// @code
325/// #if defined(BSLS_PLATFORM_OS_UNIX)
326/// rc = unsetenv("SOCKDIR"); // 'SOCKDIR' has precedence over 'TMPDIR'.
327/// assert(0 == rc);
328///
329/// const char *expectedDirectory = getenv("TMPDIR");
330/// #elif defined(BSLS_PLATFORM_OS_WINDOWS)
331/// const char *expectedDirectory = "\\\\.\\pipe\\";
332/// #else
333/// #error "Unexpected platform."
334/// #endif
335/// @endcode
336/// Then, start listening for incoming messages at pipe having the name based on
337/// on the name "MyApplication.CTRL". To avoid collisions when this test case
338/// is run simultaneously on a single machine (or on different machines sharing
339/// an NFS mount), we will append the hostname and process ID to the base name.
340/// @code
341/// const char *hostname = bsl::getenv("HOSTNAME");
342/// if (!hostname) hostname = "Windows";
343/// bsl::ostringstream ss;
344/// ss << "MyApplication.CTRL."
345/// << hostname << '.'
346/// << bdls::ProcessUtil::getProcessId();
347/// bsl::string pipeBaseName = ss.str();
348/// rc = taskManager.start(pipeBaseName);
349/// assert(0 == rc);
350/// @endcode
351/// Next, for expository purposes, confirm that a pipe of that name exists in
352/// the expected directory and is open for reading.
353/// @code
354/// const bsl::string_view pipeName = taskManager.pipeName();
355///
356/// assert(bdls::PathUtil::isAbsolute (pipeName));
357/// #ifdef BSLS_PLATFORM_OS_UNIX
358/// assert(bdls::PipeUtil::isOpenForReading(pipeName));
359/// #endif
360///
361/// bsl::string canonicalDirname, canonicalLeafName;
362///
363/// bdls::PathUtil::getDirname(&canonicalDirname, pipeName);
364/// bdls::PathUtil::getLeaf (&canonicalLeafName, pipeName);
365///
366/// assert(0 == bsl::strcmp(expectedDirectory, canonicalDirname.c_str()));
367/// bdlb::String::toLower(&pipeBaseName);
368/// assert(pipeBaseName == canonicalLeafName);
369/// @endcode
370/// Notice that given `baseName` has been canonically converted to lowercase.
371///
372/// Now, our application can continue doing useful work while the background
373/// thread monitors the named pipe for incoming messages:
374/// @code
375/// while (!done) {
376/// // Do useful work while background thread responds to incoming
377/// // commands from the named pipe.
378/// }
379///
380/// return 0;
381/// }
382/// @endcode
383/// Finally, in some other programming context, say `mySender`, a context in
384/// another process that has been passed the value of `pipeName`, control
385/// messages can be sent to `myApplication1` above.
386/// @code
387/// /// Write control messages into the pipe named by the specified `pipeName`.
388/// void mySender(const bsl::string& pipeName)
389/// {
390/// int rc;
391/// rc = bdls::PipeUtil::send(pipeName, "LoG GET\n");
392/// assert(0 == rc);
393/// rc = bdls::PipeUtil::send(pipeName, "Log SET 4\n");
394/// assert(0 == rc);
395/// rc = bdls::PipeUtil::send(pipeName, "log GET\n");
396/// assert(0 == rc);
397/// rc = bdls::PipeUtil::send(pipeName, "\n"); // empty
398/// assert(0 == rc);
399/// rc = bdls::PipeUtil::send(pipeName, "RESET\n"); // invalid
400/// assert(0 == rc);
401/// rc = bdls::PipeUtil::send(pipeName, "RESTART\n");
402/// assert(0 == rc);
403/// rc = bdls::PipeUtil::send(pipeName, "EXIT\n");
404/// assert(0 == rc);
405/// }
406/// @endcode
407/// Notice that:
408///
409/// * Each message must be terminated by a newline character.
410/// * Although each registered message prefix was all capital letters, the
411/// prefix field in the sent message is case insensitive -- "LoG", "Log", and
412/// "log" all invoke the intended handler. If we wanted case insensitivity
413/// for the subcommands "GET" and "SET" we would change of implementation of
414/// `onLog` accordingly.
415/// * The empty message and the unregistered "RESET" message are silently
416/// ignored. The console output (see below) shows no indication that these
417/// were sent.
418///
419/// The console log of our application shows the response for each received
420/// control message. In general, these messages will be interleaved with the
421/// output of the "useful work" done in the `for` loop of 'myApplicaton1.
422/// @code
423/// onLog
424/// LOG LEVEL IS NOW: 0
425/// onLog
426/// LOG LEVEL SET TO: 4
427/// onLog
428/// LOG LEVEL IS NOW: 4
429/// onRestart
430/// onExit
431/// @endcode
432/// @}
433/** @} */
434/** @} */
435
436/** @addtogroup bal
437 * @{
438 */
439/** @addtogroup balb
440 * @{
441 */
442/** @addtogroup balb_pipetaskmanager
443 * @{
444 */
445
446#include <balscm_version.h>
447
448#include <balb_controlmanager.h>
450
451#include <bslma_allocator.h>
452
454
455#include <bsls_assert.h>
456
457#include <bsl_memory.h> // 'bsl::shared_ptr' 'bsl::allocate_shared'
458#include <bsl_string.h>
459#include <bsl_string_view.h>
460
461
462namespace balb {
463
464 // =====================
465 // class PipeTaskManager
466 // =====================
467
468/// This class provides a mechanism route messages received on a named pipe
469/// to the registered handler (functor).
470///
471/// See @ref balb_pipetaskmanager
473
474 // DATA
475 bslma::Allocator *d_allocator_p; // allocator (held)
476 PipeControlChannel *d_controlChannel_p; // message IPC mech.
477 bsl::shared_ptr<ControlManager> d_controlManager_p; // callback registry
478
479 private:
480 // NOT IMPLEMENTED
481 PipeTaskManager(const PipeTaskManager& ); // = delete
482 PipeTaskManager& operator=(const PipeTaskManager& ); // = delete
483
484 public:
485 // TRAITS
488
489 // CREATORS
490
491 /// Create a task manager having no message handlers. Optionally
492 /// specify a `basicAllocator` used to supply memory. If
493 /// `basicAllocator` is 0, the currently installed default allocator is
494 /// used. Message handlers can be supplied using the return value of
495 /// the `controlManager` method. If that return value is used to create
496 /// other `PipeTaskManager` objects, this object (the owner of the
497 /// internal `ControlManager` must outlive those other objects. The
498 /// `start` method must be called successfully before messages will be received (on a separate thread created by `start`).
499 ///
500 /// \note Note that the
501 /// name of the message pipe is supplied as an argument to `start`.
502 explicit PipeTaskManager(bslma::Allocator *basicAllocator = 0);
503
504 /// Create a task manager that uses the handlers of the specified shared
505 /// `controlManager`. Optionally specify a `basicAllocator` used to
506 /// supply memory. If `basicAllocator` is 0, the currently installed
507 /// default allocator is used. The `start` method must be called
508 /// successfully before messages will be received (on a separate thread created by `start`).
509 ///
510 /// \note Note that the name of the message pipe is
511 /// supplied as an argument to `start`. Also note that the handlers of
512 /// `controlManager` can be manipulated via the return value of the
513 /// `controlManager` method. Finally note that the allocator of
514 /// `controlManger` need not equal `basicAllocator`.
515 explicit
517 bslma::Allocator *basicAllocator = 0);
518
519 /// Shutdown message handling, and release the shared reference to the
520 /// `controlManager` (destroying the `ConstrolManager` and its message
521 /// handlers if this is the last shared reference), and destroy this
522 /// object.
524
525 // MANIPULATORS
526
527 /// Return a non-`const` reference to the `ControlManager` object of
528 /// this `PipeTaskManager`.
530
531// BDE_VERIFY pragma: -FABC01 // not in alphanumeric order
532
533 /// Create a named pipe using the specified `pipeBasename` (not a
534 /// pathname), and execute the task manager event processor in a
535 /// background thread. Return 0 on success, and a non-zero value
536 /// otherwise. See {Requirements for the Named Pipe} for expectations
537 /// for `pipeBasename`. After a successful return, calls to `start`
538 /// fail until `stop` has been called (successfully); afterwards,
539 /// `start` can be called again with the same or some other `pipeBasename`.
540 ///
541 /// \note Note that the `pipeName()` method provides the
542 /// (full) pathname to the created named pipe.
543 int start(const bsl::string_view& pipeBasename);
544
545 /// Stop processing incoming messages by the background thread. If a
546 /// handler is executing at the time of invocation, that handler is
547 /// allowed to complete. This method does not block the caller, and the
548 /// background thread persists until it is joined by a call to `stop`.
549 ///
550 /// \note Note that `shutdown` and `stop` are typically called in succession.
551 void shutdown();
552
553 /// Block until the background processing thread has shutdown (which
554 /// must be initiated by a separate call to `shutdown`) then join the
555 /// background thread, remove the named pipe, and return. Return 0 on
556 /// success, and a non-zero value otherwise. If `shutdown` has not been
557 /// called, this method will block indefinitely until another thread
558 /// calls `shutdown`. Once `stop` has returned, `start` can be called again with the same or a different named pipe.
559 ///
560 /// \note Note that frequently
561 /// user code will call `shutdown` and then immediately call `stop` on a
562 /// `TaskManager` object.
563 int stop();
564
565// BDE_VERIFY pragma: +FABC01 // not in alphanumeric order
566
567 // ACCESSORS
568
569 /// Return a `const` reference to the `ControlManager` object of this
570 /// `PipeTaskManager`.
572
573 /// Return the path of the named pipe used by the implementation.
574 ///
575 /// \pre The behavior is undefined unless the task manager has been started.
576 const bsl::string& pipeName() const;
577
578 // Aspects
579
580 /// Return the allocator used by this object to supply memory.
581 ///
582 /// \note Note that if no allocator was supplied at construction the default
583 /// allocator in effect at construction is used.
585};
586
587// ============================================================================
588// INLINE DEFINITIONS
589// ============================================================================
590
591 // ---------------------
592 // class PipeTaskManager
593 // ---------------------
594
595// MANIPULATORS
596inline
598{
599 return *d_controlManager_p;
600}
601
602inline
604{
605 d_controlChannel_p->shutdown();
606}
607
608inline
610{
611 d_controlChannel_p->stop();
612 return 0;
613}
614
615// ACCESSORS
616inline
618{
619 return *d_controlManager_p;
620}
621
622inline
624{
625 BSLS_ASSERT(d_controlChannel_p);
626
627 return d_controlChannel_p->pipeName();
628}
629
630 // Aspects
631
632inline
634{
635 return d_allocator_p;
636}
637
638} // close package namespace
639
640
641#endif
642
643// ----------------------------------------------------------------------------
644// Copyright 2023 Bloomberg Finance L.P.
645//
646// Licensed under the Apache License, Version 2.0 (the "License");
647// you may not use this file except in compliance with the License.
648// You may obtain a copy of the License at
649//
650// http://www.apache.org/licenses/LICENSE-2.0
651//
652// Unless required by applicable law or agreed to in writing, software
653// distributed under the License is distributed on an "AS IS" BASIS,
654// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
655// See the License for the specific language governing permissions and
656// limitations under the License.
657// ----------------------------- END-OF-FILE ----------------------------------
658
659/** @} */
660/** @} */
661/** @} */
Definition balb_controlmanager.h:153
Definition balb_pipecontrolchannel.h:316
const bsl::string & pipeName() const
Return the fully qualified system name of the pipe.
Definition balb_pipecontrolchannel.h:603
Definition balb_pipetaskmanager.h:472
bslma::Allocator * allocator() const
Definition balb_pipetaskmanager.h:633
int stop()
Definition balb_pipetaskmanager.h:609
void shutdown()
Definition balb_pipetaskmanager.h:603
int start(const bsl::string_view &pipeBasename)
BSLMF_NESTED_TRAIT_DECLARATION(PipeTaskManager, bslma::UsesBslmaAllocator)
PipeTaskManager(bslma::Allocator *basicAllocator=0)
PipeTaskManager(bsl::shared_ptr< ControlManager > &controlManager, bslma::Allocator *basicAllocator=0)
const bsl::string & pipeName() const
Definition balb_pipetaskmanager.h:623
balb::ControlManager & controlManager()
Definition balb_pipetaskmanager.h:597
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
Definition bslstl_sharedptr.h:1838
Definition bslma_allocator.h:545
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition balb_controlmanager.h:144
Definition bslma_usesbslmaallocator.h:344