BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlmt_eventscheduler.h
Go to the documentation of this file.
1/// @file bdlmt_eventscheduler.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlmt_eventscheduler.h -*-C++-*-
8#ifndef INCLUDED_BDLMT_EVENTSCHEDULER
9#define INCLUDED_BDLMT_EVENTSCHEDULER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlmt_eventscheduler bdlmt_eventscheduler
15/// @brief Provide a thread-safe recurring and one-time event scheduler.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlmt
19/// @{
20/// @addtogroup bdlmt_eventscheduler
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlmt_eventscheduler-purpose"> Purpose</a>
25/// * <a href="#bdlmt_eventscheduler-classes"> Classes </a>
26/// * <a href="#bdlmt_eventscheduler-metrics"> Metrics </a>
27/// * <a href="#bdlmt_eventscheduler-description"> Description </a>
28/// * <a href="#bdlmt_eventscheduler-comparison-to-bdlmt-timereventscheduler"> Comparison to bdlmt::TimerEventScheduler </a>
29/// * <a href="#bdlmt_eventscheduler-events-scheduled-while-the-scheduler-is-not-dispatching"> Events Scheduled while the Scheduler is not Dispatching </a>
30/// * <a href="#bdlmt_eventscheduler-thread-safety-and-raw-event-pointers"> Thread Safety and "Raw" Event Pointers </a>
31/// * <a href="#bdlmt_eventscheduler-the-dispatcher-thread-and-the-dispatcher-functor"> The Dispatcher Thread and the Dispatcher Functor </a>
32/// * <a href="#bdlmt_eventscheduler-timer-resolution-and-order-of-execution"> Timer Resolution and Order of Execution </a>
33/// * <a href="#bdlmt_eventscheduler-supported-clock-types"> Supported Clock Types </a>
34/// * <a href="#bdlmt_eventscheduler-scheduling-using-a-bsl-chrono-time_point"> Scheduling Using a bsl::chrono::time_point </a>
35/// * <a href="#bdlmt_eventscheduler-scheduling-using-a-bsls-timeinterval"> Scheduling Using a bsls::TimeInterval </a>
36/// * <a href="#bdlmt_eventscheduler-event-clock-substitution"> Event Clock Substitution </a>
37/// * <a href="#bdlmt_eventscheduler-thread-name-for-dispatcher-thread"> Thread Name for Dispatcher Thread </a>
38/// * <a href="#bdlmt_eventscheduler-usage"> Usage </a>
39/// * <a href="#bdlmt_eventscheduler-example-1-simple-clock"> Example 1: Simple Clock </a>
40/// * <a href="#bdlmt_eventscheduler-example-2-server-timeouts"> Example 2: Server Timeouts </a>
41/// * <a href="#bdlmt_eventscheduler-example-3-using-the-test-time-source"> Example 3: Using the Test Time Source </a>
42///
43/// # Purpose {#bdlmt_eventscheduler-purpose}
44/// Provide a thread-safe recurring and one-time event scheduler.
45///
46/// # Classes {#bdlmt_eventscheduler-classes}
47///
48/// - bdlmt::EventScheduler: a thread-safe event scheduler
49/// - bdlmt::EventSchedulerEventHandle: handle to a single scheduled event
50/// - bdlmt::EventSchedulerRecurringEventHandle: handle to a recurring event
51/// - bdlmt::EventSchedulerTestTimeSource: class for testing time changes
52///
53/// # Metrics {#bdlmt_eventscheduler-metrics}
54///
55///
56/// * `bde.startlag`
57/// > seconds of delay in starting the next event (may be 0.0)
58///
59/// Associated Metric Attributes:
60/// * object type name: "bdlmt.eventscheduler"
61/// * object type abbreviation: "es"
62///
63/// @see bdlmt_timereventscheduler
64///
65/// # Description {#bdlmt_eventscheduler-description}
66/// This component provides a thread-safe event scheduler.
67/// `bdlmt::EventScheduler`, that implements methods to schedule and cancel
68/// recurring and one-time events. All of the callbacks for these events are
69/// processed by a separate thread (called the dispatcher thread). By default
70/// the callbacks are also executed in the dispatcher thread, but that behavior
71/// can be altered by providing a dispatcher functor at creation time (see the
72/// section {The Dispatcher Thread and the Dispatcher Functor}).
73///
74/// Events may be referred to by `bdlmt::EventSchedulerEventHandle` and
75/// `bdlmt::EventSchedulerRecurringEventHandle` objects, which clean up after
76/// themselves when they go out of scope, or by `Event` and `RecurringEvent`
77/// pointers, which must be released using `releaseEventRaw`. Such pointers are
78/// used in the "Raw" API of this class and must be used carefully. Note that
79/// the Handle objects have an implicit conversion to the corresponding `Event`
80/// or `RecurringEvent` pointer types, effectively providing extra overloads for
81/// methods that take a `const Event*` to also take a `const EventHandle&`.
82///
83/// ## Comparison to bdlmt::TimerEventScheduler {#bdlmt_eventscheduler-comparison-to-bdlmt-timereventscheduler}
84///
85///
86/// This component was written after @ref bdlmt_timereventscheduler , which suffered
87/// from a couple of short-comings:
88/// 1. there was a maximum number of events it could manage, and
89/// 2. it was inefficient at dealing with large numbers of events
90///
91/// This component addresses both those problems -- there is no limit on the
92/// number of events it can manage, and it is more efficient at dealing with
93/// large numbers of events. The disadvantage of this component relative to
94/// @ref bdlmt_timereventscheduler is that handles referring to managed events in a
95/// `bdlmt::EventScheduler` are reference-counted and need to be released, while
96/// handles of events in a `bdlmt::TimerEventScheduler` are integral types that
97/// do not need to be released.
98///
99/// ## Events Scheduled while the Scheduler is not Dispatching {#bdlmt_eventscheduler-events-scheduled-while-the-scheduler-is-not-dispatching}
100///
101///
102/// Events may be scheduled before invoking `start()` and after invoking
103/// `stop()`. Invoking `start()` and `stop()` does not cancel any events.
104/// Events scheduled to run while the scheduler is not dispatching will be
105/// handled normally once `start()` is invoked; events will be dispatched in
106/// order of their scheduled times such that no event is dispatched before its
107/// scheduled time.
108///
109/// ## Thread Safety and "Raw" Event Pointers {#bdlmt_eventscheduler-thread-safety-and-raw-event-pointers}
110///
111///
112/// `bdlmt::EventScheduler` is thread-safe and thread-enabled, meaning that
113/// multiple threads may use their own instances of the class or use a shared
114/// instance without further synchronization. The thread safety and correct
115/// behavior of the component depend on the correct usage of `Event` pointers,
116/// which refer to scheduled events in the "Raw" API of this class. In
117/// particular:
118/// * Every `Event*` and `RecurringEvent*` populated by `scheduleEventRaw`
119/// and `scheduleRecurringEventRaw` must be released using `releaseEventRaw.`
120/// - Pointers are not released automatically when events are completed.
121/// - Pointers are not released automatically when events are canceled.
122/// - Events are not canceled when pointers to them are released.
123/// * Pointers must not be used after being released.
124/// * Pointers must never be shared or duplicated without using
125/// `addEventRefRaw` and `addRecurringEventRefRaw` to get additional
126/// references; *each* such added reference must be released separately.
127///
128/// `bdlmt::EventSchedulerEventHandle` and
129/// `bdlmt::EventSchedulerRecurringEventHandle` are **const thread-safe**. It
130/// is not safe for multiple threads to invoke non-`const` methods on the same
131/// `EventHandle` or `RecurringEventHandle` object concurrently.
132///
133/// ## The Dispatcher Thread and the Dispatcher Functor {#bdlmt_eventscheduler-the-dispatcher-thread-and-the-dispatcher-functor}
134///
135///
136/// The scheduler creates a single separate thread (called the *dispatcher*
137/// *thread*) to process all the callbacks. The dispatcher thread executes the
138/// callbacks by passing them to the dispatcher functor (optionally specified at
139/// creation time). The default dispatcher functor simply invokes the passed
140/// callback, effectively executing it in the dispatcher thread. Users can
141/// alter this behavior by defining their own dispatcher functor (for example in
142/// order to use a thread pool or a separate thread to run the callbacks). Note
143/// that the user-supplied functor will still be run in the dispatcher thread.
144///
145/// CAVEAT: Using a dispatcher functor such as the example above (to execute the
146/// callback in a separate thread) violates the guarantees of
147/// ``cancelEventAndWait()``. Users who specify a dispatcher functor that
148/// transfers the event to another thread for execution should not use
149/// ``cancelEventAndWait()``, and should instead ensure that the lifetime of any
150/// object bound to an event exceeds the lifetime of the mechanism used by the
151/// customized dispatcher functor.
152///
153/// ## Timer Resolution and Order of Execution {#bdlmt_eventscheduler-timer-resolution-and-order-of-execution}
154///
155///
156/// It is intended that recurring and one-time events are processed as closely
157/// as possible to their respective time values, and that they are processed in
158/// the order scheduled. However, this component **guarantees** only that
159/// events will not be executed before their scheduled time. Generally, events
160/// that are scheduled more than 1 microsecond apart will be executed in the
161/// order scheduled; but different behavior may be observed when events are
162/// submitted after (or shortly before) their scheduled time.
163///
164/// When events are executed in the dispatcher thread and take longer to
165/// complete than the time between events, the dispatcher can fall behind. In
166/// this case, events will be executed in the correct order as soon as the
167/// dispatcher thread becomes available; once the backlog is worked off, events
168/// will be executed at or near their scheduled times.
169///
170/// ## Supported Clock Types {#bdlmt_eventscheduler-supported-clock-types}
171///
172///
173/// An `EventScheduler` optionally accepts a clock type at construction
174/// indicating the clock by which it will internally schedule events. The clock
175/// type may be indicated by either a `bsls::SystemClockType::Enum` value, a
176/// `bsl::chrono::system_clock` object (which is equivalent to specifying
177/// `e_REALTIME`), or a `bsl::chrono::steady_clock` object (equivalent to
178/// specifying `e_MONOTONIC`). If a clock type is not specified, `e_REALTIME`
179/// is used.
180///
181/// ### Scheduling Using a bsl::chrono::time_point {#bdlmt_eventscheduler-scheduling-using-a-bsl-chrono-time_point}
182///
183///
184/// When creating either a one-time or recurring event, clients may pass a
185/// `bsl::chrono::time_point` indicating the time the event should occur. This
186/// @ref time_point object can be associated with an arbitrary clock. If the
187/// @ref time_point is associated with a different clock than was indicated at
188/// construction of the event scheduler, those time points are converted to be
189/// relative to the event scheduler's clock for processing. A possible
190/// implementation of such a conversion would be:
191/// @code
192/// bsls::TimeInterval(time - t_CLOCK::now()) + eventScheduler.now()
193/// @endcode
194/// where `time` is a @ref time_point , `t_CLOCK` is the clock associated with
195/// `time`, and `eventScheduler` is the `EventScheduler` on which the event is
196/// being scheduled. Notice that the conversion adds some imprecision and
197/// overhead to evaluation of the event. An event scheduler guarantees an event
198/// will occur at or after the supplied @ref time_point , even if that @ref time_point
199/// is defined in terms of a `t_CLOCK` different from the one used by the event
200/// scheduler. If there is a discontinuity between the clock for a @ref time_point
201/// and the event scheduler's clock, additional processing overhead may result
202/// (because the event may need to be rescheduled), and the event may also occur
203/// later than what one might otherwise expect.
204///
205/// ### Scheduling Using a bsls::TimeInterval {#bdlmt_eventscheduler-scheduling-using-a-bsls-timeinterval}
206///
207///
208/// When creating either a one-time or recurring event, clients may pass a
209/// `bsls::TimeInterval` indicating the time the event should occur as an offset
210/// from an epoch. If the clock type indicated at construction is
211/// `bsls::SystemClockType::e_REALTIME`, time should be expressed as an absolute
212/// offset since 00:00:00 UTC, January 1, 1970 (which matches the epoch used in
213/// `bdlt::CurrentTime::now(bsls::SystemClockType::e_REALTIME)`, and
214/// `bsl::chrono::system_clock::now()`). If the clock type indicated at
215/// construction is `bsls::SystemClockType::e_MONOTONIC`, time should be
216/// expressed as an absolute offset since the epoch of this clock (which matches
217/// the epoch used in
218/// `bdlt::CurrentTime::now(bsls::SystemClockType::e_MONOTONIC)` and
219/// `bsl::chrono::steady_clock`).
220///
221/// ## Event Clock Substitution {#bdlmt_eventscheduler-event-clock-substitution}
222///
223///
224/// For testing purposes, a class `bdlmt::EventSchedulerTestTimeSource` is
225/// provided to allow manual manipulation of the system-time observed by a
226/// `bdlmt::EventScheduler`. A test driver that interacts with a
227/// `bdlmt::EventScheduler` can use a `bdlmt::EventSchedulerTestTimeSource`
228/// object to control when scheduled events are triggered, allowing more
229/// reliable tests.
230///
231/// A `bdlmt::EventSchedulerTestTimeSource` can be constructed for any existing
232/// `bdlmt::EventScheduler` object that has not been started and has not had any
233/// events scheduled. When the `bdlmt::EventSchedulerTestTimeSource` is
234/// constructed, it will replace the clock of the `bdlmt::EventScheduler` to
235/// which it is attached. The internal clock of the
236/// `bdlmt::EventSchedulerTestTimeSource` will be initialized with an arbitrary
237/// value on construction, and will advance only when explicitly instructed to
238/// do so by a call to `bdlt::EventSchedulerTestTimeSource::advanceTime`. The
239/// current value of the internal clock can be accessed by calling
240/// `bdlt::EventSchedulerTestTimeSource::now`, or `bdlmt::EventScheduler::now`
241/// on the instance supplied to the `bdlmt::EventSchedulerTestTimeSource`.
242///
243/// Note that the initial value of `bdlt::EventSchedulerTestTimeSource::now` is
244/// intentionally not synchronized with `bsls::SystemTime::nowRealtimeClock`.
245/// All test events scheduled for a `bdlmt::EventScheduler` that is instrumented
246/// with a `bdlt::EventSchedulerTestTimeSource` should be scheduled in terms of
247/// an offset from whatever arbitrary time is reported by
248/// `bdlt::EventSchedulerTestTimeSource`. See
249/// @ref bdlmt_eventscheduler-example-3-using-the-test-time-source below for an illustration of how
250/// this is done.
251///
252/// Also note that `bdlt::EventSchedulerTestTimeSource::advanceTime`
253/// synchronizes with the dispatching thread. Specifically, `advanceTime` does
254/// not return until the dispatcher processes all events triggered by the change
255/// in current time.
256///
257/// ## Thread Name for Dispatcher Thread {#bdlmt_eventscheduler-thread-name-for-dispatcher-thread}
258///
259///
260/// To facilitate debugging, users can provide a thread name as the `threadName`
261/// attribute of the `bslmt::ThreadAttributes` argument passed to the `start`
262/// method, that will be used for the dispatcher thread. The thread name should
263/// not be used programmatically, but will appear in debugging tools on
264/// platforms that support naming threads to help users identify the source and
265/// purpose of a thread. If no `ThreadAttributes` object is passed, or if the
266/// `threadName` attribute is not set, the default value "bdl.EventSched" will
267/// be used.
268///
269/// ## Usage {#bdlmt_eventscheduler-usage}
270///
271///
272/// This section illustrates intended use of this component.
273///
274/// ### Example 1: Simple Clock {#bdlmt_eventscheduler-example-1-simple-clock}
275///
276///
277/// In this example we wish to log some statistics periodically. We define a
278/// method to store the value of a variable into an array, and set up a
279/// scheduler to call that as a recurring event.
280/// @code
281/// bsls::AtomicInt g_data; // Some global data we want to track
282/// typedef pair<bsls::TimeInterval, int> Value;
283///
284/// void saveData(vector<Value> *array)
285/// {
286/// array->push_back(Value(bsls::SystemTime::nowRealtimeClock(), g_data));
287/// }
288/// @endcode
289/// We allow the scheduler to run for a short time while changing this value and
290/// observe that the callback is executed:
291/// @code
292/// bdlmt::EventScheduler scheduler;
293/// vector<Value> values;
294///
295/// scheduler.scheduleRecurringEvent(bsls::TimeInterval(1.5),
296/// bdlf::BindUtil::bind(&saveData, &values)));
297/// scheduler.start();
298/// bsls::TimeInterval start = bsls::SystemTime::nowRealtimeClock();
299/// while ((bsls::SystemTime::nowRealtimeClock() -
300/// start).totalSecondsAsDouble() < 7) {
301/// ++g_data;
302/// }
303/// scheduler.stop();
304/// assert(values.size() >= 4);
305/// for (int i = 0; i < (int) values.size(); ++i) {
306/// cout << "At " << bdlt::EpochUtil::convertFromTimeInterval(
307/// values[i].first) <<
308/// " g_data was " << values[i].second << endl;
309/// }
310/// @endcode
311/// This will display, e.g.:
312/// @code
313/// At 26OCT2020_23:51:51.097283 g_data was 8008406
314/// At 26OCT2020_23:51:52.597287 g_data was 16723918
315/// At 26OCT2020_23:51:54.097269 g_data was 24563722
316/// At 26OCT2020_23:51:55.597262 g_data was 30291748
317/// @endcode
318///
319/// ### Example 2: Server Timeouts {#bdlmt_eventscheduler-example-2-server-timeouts}
320///
321///
322/// The following example shows how to use a `bdlmt::EventScheduler` to
323/// implement a timeout mechanism in a server. `my_Session` maintains several
324/// connections. It closes a connection if the data for it does not arrive
325/// before a timeout (specified at the server creation time).
326///
327/// Because the timeout is relative to the arrival of data, it is best to use a
328/// "monotonic" clock that advances at a steady rate, rather than a "wall" clock
329/// that may fluctuate to reflect real time adjustments.
330/// @code
331/// /// This class encapsulates the data and state associated with a
332/// /// connection and provides a method `processData` to process the
333/// /// incoming data for the connection.
334/// class my_Session{
335/// public:
336///
337/// /// Process the specified `data` of the specified `length`. (TBD)
338/// int processData(void *data, int length);
339/// };
340///
341/// /// This class implements a server maintaining several connections.
342/// /// A connection is closed if the data for it does not arrive
343/// /// before a timeout (specified at the server creation time).
344/// class my_Server {
345///
346/// struct Connection {
347/// bdlmt::EventSchedulerEventHandle d_timerId; // handle for timeout
348/// // event
349///
350/// my_Session *d_session_p; // session for this
351/// // connection
352/// };
353///
354/// bsl::vector<Connection*> d_connections; // maintained connections
355/// bdlmt::EventScheduler d_scheduler; // timeout event scheduler
356/// bsls::TimeInterval d_ioTimeout; // time out
357///
358/// /// Add the specified `connection` to this server and schedule
359/// /// the timeout event that closes this connection if the data
360/// /// for this connection does not arrive before the timeout.
361/// void newConnection(Connection *connection);
362///
363/// /// Close the specified `connection` and remove it from this server.
364/// void closeConnection(Connection *connection);
365///
366/// /// Return if the specified `connection` has already timed-out.
367/// /// If not, cancel the existing timeout event for the `connection`,
368/// /// process the specified `data` of the specified `length` and
369/// /// schedule a new timeout event that closes the `connection` if
370/// /// the data does not arrive before the timeout.
371/// void dataAvailable(Connection *connection, void *data, int length);
372///
373/// public:
374///
375/// /// Create a `my_Server` object with a timeout value of `ioTimeout`
376/// /// seconds. Optionally specify a `allocator` used to supply memory. If
377/// /// `allocator` is 0, the currently installed default allocator is used.
378/// my_Server(const bsls::TimeInterval& ioTimeout,
379/// bslma::Allocator *allocator = 0);
380///
381/// /// Perform the required clean-up and destroy this object.
382/// ~my_Server();
383/// };
384///
385/// my_Server::my_Server(const bsls::TimeInterval& ioTimeout,
386/// bslma::Allocator *alloc)
387/// : d_connections(alloc)
388/// , d_scheduler(bsls::SystemClockType::e_MONOTONIC, alloc)
389/// , d_ioTimeout(ioTimeout)
390/// {
391/// // TBD: logic to start monitoring the arriving connections or data
392///
393/// d_scheduler.start();
394/// }
395///
396/// my_Server::~my_Server()
397/// {
398/// // TBD: logic to clean up
399///
400/// d_scheduler.stop();
401/// }
402///
403/// void my_Server::newConnection(my_Server::Connection *connection)
404/// {
405/// // TBD: logic to add 'connection' to 'd_connections'
406///
407/// // setup the timeout for data arrival
408/// d_scheduler.scheduleEvent(
409/// &connection->d_timerId,
410/// d_scheduler.now() + d_ioTimeout,
411/// bdlf::BindUtil::bind(&my_Server::closeConnection, this, connection));
412/// }
413///
414/// void my_Server::closeConnection(my_Server::Connection *connection)
415/// {
416/// // TBD: logic to close the 'connection' and remove it from 'd_ioTimeout'
417/// }
418///
419/// void my_Server::dataAvailable(my_Server::Connection *connection,
420/// void *data,
421/// int length)
422/// {
423/// // If connection has already timed out and closed, simply return.
424/// if (d_scheduler.cancelEvent(connection->d_timerId)) {
425/// return; // RETURN
426/// }
427///
428/// // process the data
429/// connection->d_session_p->processData(data, length);
430///
431/// // setup the timeout for data arrival
432/// d_scheduler.scheduleEvent(
433/// &connection->d_timerId,
434/// d_scheduler.now() + d_ioTimeout,
435/// bdlf::BindUtil::bind(&my_Server::closeConnection, this, connection));
436/// }
437/// @endcode
438///
439/// ### Example 3: Using the Test Time Source {#bdlmt_eventscheduler-example-3-using-the-test-time-source}
440///
441///
442/// For testing purposes, the class `bdlmt::EventSchedulerTestTimeSource` is
443/// provided to allow a test to manipulate the system-time observed by a
444/// `bdlmt::EventScheduler` in order to control when events are triggered.
445/// After a scheduler is constructed, a `bdlmt::EventSchedulerTestTimeSource`
446/// object can be created atop the scheduler. A test can then use the test
447/// time-source to advance the scheduler's observed system-time in order to
448/// dispatch events in a manner coordinated by the test. Note that a
449/// `bdlmt::EventSchedulerTestTimeSource` **must** be created on an
450/// event-scheduler before any events are scheduled, or the event-scheduler is
451/// started.
452///
453/// This example shows how the clock may be altered:
454/// @code
455/// void myCallbackFunction() {
456/// puts("Event triggered!");
457/// }
458///
459/// void testCase() {
460/// // Create the scheduler
461/// bdlmt::EventScheduler scheduler;
462///
463/// // Create the time-source.
464/// // Install the time-source in the scheduler.
465/// bdlmt::EventSchedulerTestTimeSource timeSource(&scheduler);
466///
467/// // Retrieve the initial time held in the time-source.
468/// bsls::TimeInterval initialAbsoluteTime = timeSource.now();
469///
470/// // Schedule a single-run event at a 35s offset.
471/// scheduler.scheduleEvent(initialAbsoluteTime + 35,
472/// bsl::function<void()>(&myCallbackFunction));
473///
474/// // Schedule a 30s recurring event.
475/// scheduler.scheduleRecurringEvent(bsls::TimeInterval(30),
476/// bsl::function<void()>(
477/// &myCallbackFunction));
478///
479/// // Start the dispatcher thread.
480/// scheduler.start();
481///
482/// // Advance the time by 40 seconds so that each
483/// // event will run once.
484/// timeSource.advanceTime(bsls::TimeInterval(40));
485///
486/// // The line "Event triggered!" should now have
487/// // been printed to the console twice.
488///
489/// scheduler.stop();
490/// }
491/// @endcode
492/// Note that this feature should be used only for testing purposes, never in
493/// production code.
494/// @}
495/** @} */
496/** @} */
497
498/** @addtogroup bdl
499 * @{
500 */
501/** @addtogroup bdlmt
502 * @{
503 */
504/** @addtogroup bdlmt_eventscheduler
505 * @{
506 */
507
508#include <bdlscm_version.h>
509
510#include <bdlcc_skiplist.h>
511
512#include <bdlm_metricsregistry.h>
513
514#include <bdlf_bind.h>
515#include <bdlf_placeholder.h>
516
517#include <bslmt_condition.h>
518#include <bslmt_lockguard.h>
519#include <bslmt_mutex.h>
521#include <bslmt_threadutil.h>
522
523#include <bslma_allocator.h>
525
526#include <bslmf_allocatorargt.h>
528
529#include <bsls_assert.h>
530#include <bsls_atomic.h>
531#include <bsls_libraryfeatures.h>
532#include <bsls_review.h>
533#include <bsls_systemclocktype.h>
534#include <bsls_timeinterval.h>
535#include <bsls_types.h>
536
537#include <bsl_functional.h>
538#include <bsl_memory.h>
539#include <bsl_optional.h>
540#include <bsl_string.h>
541#include <bsl_utility.h>
542
543#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
544#include <bslmt_chronoutil.h>
545
546#include <bsl_chrono.h>
547#endif
548
549
550namespace bdlmt {
551
554class EventSchedulerTestTimeSource_Data;
555
556 // ====================
557 // class EventScheduler
558 // ====================
559
560/// This class provides a thread-safe event scheduler that executes
561/// callbacks in a separate "dispatcher thread." `start` must be invoked to
562/// start dispatching the callbacks. `stop` pauses the dispatching of the
563/// callbacks without removing the pending events.
564///
565/// See @ref bdlmt_eventscheduler
567
568 private:
569 // PRIVATE TYPES
570
571 // ================
572 // struct EventData
573 // ================
574
575 /// This `struct` encapsulates all of the information for a
576 /// non-recurring event.
577 ///
578 /// See @ref bdlmt_eventscheduler
579 struct EventData {
580
581 public:
582 // DATA
583
584 /// user-supplied callback invoked when associated event triggers
585 bsl::function<void()> d_callback;
586
587 /// a function that returns the difference, in microseconds, between
588 /// when the scheduled event is meant to occur and the current time
589 bsl::function<bsls::Types::Int64()> d_nowOffset;
590
591 private:
592 // NOT IMPLEMENTED
593 EventData& operator=(const EventData&);
594
595 public:
596 // TRAITS
598
599 // CREATORS
600
601 /// Create an `EventData` from the specified `callback` and
602 /// `nowOffset`. Optionally specify a `basicAllocator` used to
603 /// supply memory. If `basicAllocator` is 0, the currently
604 /// installed default allocator is used.
605 EventData(
606 const bsl::function<void()>& callback,
607 const bsl::function<bsls::Types::Int64()>& nowOffset,
608 bslma::Allocator *basicAllocator = 0)
609 : d_callback(bsl::allocator_arg, basicAllocator, callback)
610 , d_nowOffset(bsl::allocator_arg, basicAllocator, nowOffset)
611 {
612 }
613
614 /// Create an `EventData` object having the value of the specified
615 /// `original` object. Optionally specify a `basicAllocator` used
616 /// to supply memory. If `basicAllocator` is 0, the currently
617 /// installed default allocator is used.
618 EventData(const EventData& original,
619 bslma::Allocator *basicAllocator = 0)
620 : d_callback(bsl::allocator_arg, basicAllocator, original.d_callback)
621 , d_nowOffset(bsl::allocator_arg, basicAllocator, original.d_nowOffset)
622 {
623 }
624 };
625
626 // =========================
627 // struct RecurringEventData
628 // =========================
629
630 /// This `struct` encapsulates all of the information for a recurring
631 /// event.
632 ///
633 /// See @ref bdlmt_eventscheduler
634 struct RecurringEventData {
635
636 public:
637 // DATA
638
639 /// the time between calls (in microseconds)
640 bsls::TimeInterval d_interval;
641
642 /// user-supplied callback invoked when associated event triggers
643 bsl::function<void()> d_callback;
644
645 /// a function that returns the difference, in microseconds, between
646 /// when the scheduled event is meant to occur and the current time
647 bsl::function<bsls::Types::Int64(int)> d_nowOffset;
648
649 /// the index of the recurring event (starting with 0); passed to
650 /// `d_nowOffset` to determine the time of the next invocation of
651 /// `d_callback`
652 int d_eventIdx;
653
654 private:
655 // NOT IMPLEMENTED
656 RecurringEventData& operator=(const RecurringEventData&);
657
658 public:
659 // TRAITS
660 BSLMF_NESTED_TRAIT_DECLARATION(RecurringEventData,
662
663 // CREATORS
664
665 /// Create a `RecurringEventData` from the specified `interval`,
666 /// `callback`, and `nowOffset`. Optionally specify a
667 /// `basicAllocator` used to supply memory. If `basicAllocator` is
668 /// 0, the currently installed default allocator is used.
669 RecurringEventData(
670 const bsls::TimeInterval& interval,
671 const bsl::function<void()>& callback,
672 const bsl::function<bsls::Types::Int64(int)>& nowOffset,
673 bslma::Allocator *basicAllocator = 0)
674 : d_interval(interval)
675 , d_callback(bsl::allocator_arg, basicAllocator, callback)
676 , d_nowOffset(bsl::allocator_arg, basicAllocator, nowOffset)
677 , d_eventIdx(0)
678 {
679 }
680
681 /// Create a `RecurringEventData` object having the value of the
682 /// specified `original` object. Optionally specify a
683 /// `basicAllocator` used to supply memory. If `basicAllocator` is
684 /// 0, the currently installed default allocator is used.
685 RecurringEventData(const RecurringEventData& original,
686 bslma::Allocator *basicAllocator = 0)
687 : d_interval(original.d_interval)
688 , d_callback(bsl::allocator_arg, basicAllocator, original.d_callback)
689 , d_nowOffset(bsl::allocator_arg, basicAllocator, original.d_nowOffset)
690 , d_eventIdx(original.d_eventIdx)
691 {
692 }
693 };
694
696 RecurringEventData> RecurringEventQueue;
697
699
701
702 // FRIENDS
706
707 public:
708 // PUBLIC TYPES
709 struct Event {};
710
711 /// Pointers to the opaque structures `Event` and `RecurringEvent` are
712 /// populated by the "Raw" API of `EventScheduler`.
713 ///
714 /// See @ref bdlmt_eventscheduler
715 struct RecurringEvent {};
716
718
720
721 /// Defines a type alias for the dispatcher functor type.
722 typedef bsl::function<void(const bsl::function<void()>&)>
724
725 private:
726 // NOT IMPLEMENTED
728 EventScheduler& operator=(const EventScheduler&);
729
730 private:
731 // PRIVATE CLASS DATA
732 static const char s_defaultThreadName[16]; // Thread name to use when
733 // none is specified.
734
735 // PRIVATE DATA
736 CurrentTimeFunctor d_currentTimeFunctor; // when called, returns the
737 // current time the scheduler
738 // should use for the event
739 // timeline
740
741 bsls::AtomicInt64 d_cachedNow; // cached total microseconds
742
743 EventQueue d_eventQueue; // events
744
745 RecurringEventQueue d_recurringQueue; // recurring events
746
747 Dispatcher d_dispatcherFunctor; // dispatch events
748
750 d_dispatcherThread; // dispatcher thread handle
751
752 bsls::AtomicUint64 d_dispatcherThreadId; // dispatcher thread id used to
753 // implement function
754 // `isInDispatcherThread`
755
756 bslmt::Mutex d_dispatcherMutex; // serialize starting/stopping
757 // dispatcher thread
758
759 mutable bslmt::Mutex d_mutex; // synchronizes access to
760 // condition variables
761
762 bslmt::Condition d_queueCondition; // condition variable used to
763 // signal when the queues need
764 // to be checked again (when
765 // they become non-empty or get
766 // a new front member)
767
768 bslmt::Condition d_iterationCondition; // condition variable used to
769 // signal when the dispatcher
770 // is ready to enter next
771 // iteration (synchronizes
772 // `wait` methods)
773
774 bool d_running; // controls the looping of the
775 // dispatcher thread
776
777 bool d_dispatcherAwaited; // A thread is waiting for the
778 // dispatcher to complete an
779 // iteration
780
782 *d_currentRecurringEvent;
783 // Raw reference to the
784 // scheduled event being
785 // executed
786 EventQueue::Pair *d_currentEvent;
787 // Raw reference to the
788 // scheduled recurring event
789 // being executed
790
791 unsigned int d_waitCount; // count of the number of waits
792 // performed in the main
793 // dispatch loop, used in
794 // `advanceTime` to determine
795 // when to return
796
798 d_clockType; // clock type used
799
800 const bsl::string d_eventSchedulerName; // name of this scheduler
801
803 d_startLagHandle; // start lag metric handle
804
805 // PRIVATE CLASS METHODS
806
807 /// Cast the specified `handle` to an `EventQueue::Pair`.
808 static const EventQueue::Pair *castToQueuePair(const Event *handle);
809
810 /// Cast the specified `handle` to a `RecurringEventQueue::Pair`.
811 static const RecurringEventQueue::Pair *castToQueuePair(
812 const RecurringEvent *handle);
813
814 /// Return 0.
815 static bsls::Types::Int64 returnZero();
816
817 /// Return 0. The `int` argument is ignored.
818 static bsls::Types::Int64 returnZeroInt(int);
819
820#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
821 /// Return the number of microseconds between the current time and the
822 /// specified `absTime`. `absTime` is an *absolute* time represented as
823 /// an interval from some epoch, which is determined by the clock associated with the time point.
824 ///
825 /// \note Note that this method is used when
826 /// the `t_CLOCK` type used to schedule the event differs from that of
827 /// the event scheduler itself. Also note that a negative value is
828 /// returned if `absTime` is in the past.
829 template <class t_CLOCK, class t_DURATION>
830 static bsls::Types::Int64 timeUntilTrigger(
831 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& absTime);
832
833 /// Return the number of microseconds between the current time and the
834 /// scheduled time of the specified `eventIndex`th recurring event,
835 /// which starts at the specified `absTime` and repeats at the specified
836 /// `interval`. `absTime` is an *absolute* time represented as an
837 /// interval from some epoch, which is determined by the clock associated with the time point.
838 ///
839 /// \pre The behavior is undefined unless `0 <= eventIndex`.
840 ///
841 /// \note Note that this method is used when the `t_CLOCK`
842 /// type used to schedule the event differs from that of the event
843 /// scheduler itself.
844 template <class t_CLOCK,
845 class t_DURATION,
846 class t_REP_TYPE,
847 class t_PERIOD_TYPE>
848 static bsls::Types::Int64 timeUntilTriggerRecurring(
849 const bsl::chrono::time_point<t_CLOCK,
850 t_DURATION>& absTime,
851 const bsl::chrono::duration<t_REP_TYPE,
852 t_PERIOD_TYPE>& interval,
853 int eventIndex);
854#endif
855
856 // PRIVATE MANIPULATORS
857
858 /// Pick either `d_currentEvent` or `d_currentRecurringEvent` as the
859 /// next event to be executed, given that the current time is the
860 /// specified (absolute) `now` interval, and return the (absolute)
861 /// interval of the chosen event. If both `d_currentEvent` and
862 /// `d_currentRecurringEvent` are valid, release whichever one was not
863 /// chosen. If both `d_currentEvent` and `d_currentRecurringEvent` are
864 /// scheduled before `now`, choose `d_currentEvent`.
865 ///
866 /// \pre The behavior is undefined if neither `d_currentEvent` nor `d_currentRecurringEvent` is valid.
867 ///
868 /// \note Note that the argument and return value of this method
869 /// are expressed in terms of the number of microseconds elapsed since
870 /// some epoch, which is determined by the clock indicated at
871 /// construction (see {Supported Clock Types} in the component
872 /// documentation). Also note that this method may update the value of
873 /// `now` with the current system time if necessary.
874 bsls::Types::Int64 chooseNextEvent(bsls::AtomicInt64 *now);
875
876 /// While d_running is true, execute events in the event and recurring event queues at their scheduled times.
877 ///
878 /// \note Note that this method
879 /// implements the dispatching thread.
880 void dispatchEvents();
881
882
883 /// Initialize this event scheduler using the stored attributes and the
884 /// specified `metricsRegistry` and `eventSchedulerName`. If
885 /// `metricsRegistry` is 0, `bdlm::MetricsRegistry::singleton()` is
886 /// used.
887 void initialize(bdlm::MetricsRegistry *metricsRegistry,
888 const bsl::string_view& eventSchedulerName);
889
890 /// Release `d_currentRecurringEvent` and `d_currentEvent`, if they
891 /// refer to valid events.
892 void releaseCurrentEvents();
893
894 /// Schedule the callback of the specified `eventData` to be dispatched
895 /// at the specified `epochTime` truncated to microseconds. Load into
896 /// the specified `event` pointer a handle that can be used to cancel
897 /// the event (by invoking `cancelEvent`). The `epochTime` is an
898 /// absolute time represented as an interval from some epoch, which is
899 /// determined by the clock indicated at construction (see {Supported Clock Types} in the component documentation).
900 ///
901 /// \note Note that if
902 /// `epochTime` is in the past, the event is dispatched immediately.
903 void scheduleEvent(EventHandle *event,
904 const bsls::TimeInterval& epochTime,
905 const EventData& eventData);
906
907 /// Schedule the callback of the specified `eventData` to be dispatched
908 /// at the specified `epochTime` truncated to microseconds. The
909 /// `epochTime` is an absolute time represented as an interval from some
910 /// epoch, which is determined by the clock indicated at construction
911 /// (see {Supported Clock Types} in the component documentation).
912 ///
913 /// \note Note that if `epochTime` is in the past, the event is dispatched
914 /// immediately.
915 void scheduleEvent(const bsls::TimeInterval& epochTime,
916 const EventData& eventData);
917
918 /// Schedule a recurring event that invokes the callback of the
919 /// specified `eventData` with the first event dispatched at the
920 /// specified `startEpochTime` truncated to microseconds. Load into the
921 /// specified `event` pointer a handle that can be used to cancel the
922 /// event (by invoking `cancelEvent`). The `startEpochTime` is an
923 /// absolute time represented as an interval from some epoch, which is
924 /// determined by the clock indicated at construction (see {Supported
925 /// Clock Types} in the component documentation).
926 ///
927 /// \pre The behavior is undefined unless the interval of `eventData` is at least one microsecond.
928 ///
929 /// \note Note that if `startEpochTime` is in the past, the
930 /// first event is dispatched immediately, and additional
931 /// `(now() - startEpochTime) / eventData.d_interval` events will be
932 /// submitted serially.
933 void scheduleRecurringEvent(RecurringEventHandle *event,
934 const RecurringEventData& eventData,
935 const bsls::TimeInterval& startEpochTime);
936
937 /// Schedule a recurring event that invokes the callback of the
938 /// specified `eventData` with the first event dispatched at the
939 /// specified `startEpochTime` truncated to microseconds. Load into the
940 /// specified `event` pointer a handle that can be used to cancel the
941 /// event (by invoking `cancelEvent`). The `startEpochTime` is an
942 /// *absolute* time represented as an interval from some epoch, which is
943 /// determined by the clock indicated at construction (see {Supported
944 /// Clock Types} in the component documentation). The `event` pointer
945 /// must be released by invoking `releaseEventRaw` when it is no longer needed.
946 ///
947 /// \pre The behavior is undefined unless the interval of `eventData` is at least one microsecond.
948 ///
949 /// \note Note that if
950 /// `startEpochTime` is in the past, the first event is dispatched
951 /// immediately, and additional
952 /// `(now() - startEpochTime) / eventData.d_interval` events will be
953 /// submitted serially.
954 void scheduleRecurringEventRaw(RecurringEvent **event,
955 const RecurringEventData& eventData,
956 const bsls::TimeInterval& startEpochTime);
957
958 public:
959 // TRAITS
961
962 // CREATORS
963
964 /// Create an event scheduler using the default dispatcher functor (see
965 /// {The Dispatcher Thread and the Dispatcher Functor} in the
966 /// component-level documentation) and using the system realtime clock
967 /// to indicate the epoch used for all time intervals. Optionally
968 /// specify a `basicAllocator` used to supply memory. If
969 /// `basicAllocator` is 0, the currently installed default allocator is
970 /// used.
972 explicit EventScheduler(bslma::Allocator *basicAllocator);
973
974 /// Create an event scheduler using the default dispatcher functor (see
975 /// {The Dispatcher Thread and the Dispatcher Functor} in the
976 /// component-level documentation), using the system realtime clock to
977 /// indicate the epoch used for all time intervals, the specified
978 /// `eventSchedulerName` to be used to identify this event scheduler, and
979 /// the specified `metricsRegistry` to be used for reporting metrics.
980 /// If `metricsRegistry` is 0, `bdlm::MetricsRegistry::singleton()` is
981 /// used. Optionally specify a `basicAllocator` used to supply memory.
982 /// If `basicAllocator` is 0, the currently installed default allocator
983 /// is used.
984 explicit EventScheduler(const bsl::string_view& eventSchedulerName,
985 bdlm::MetricsRegistry *metricsRegistry,
986 bslma::Allocator *basicAllocator = 0);
987
988 /// Create an event scheduler using the default dispatcher functor (see
989 /// {The Dispatcher Thread and the Dispatcher Functor} in the
990 /// component-level documentation) and using the specified `clockType`
991 /// to indicate the epoch used for all time intervals (see {Supported
992 /// Clock Types} in the component documentation). Optionally specify a
993 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
994 /// the currently installed default allocator is used.
996 bslma::Allocator *basicAllocator = 0);
997
998 /// Create an event scheduler using the default dispatcher functor (see
999 /// {The Dispatcher Thread and the Dispatcher Functor} in the
1000 /// component-level documentation), using the specified `clockType` to
1001 /// indicate the epoch used for all time intervals (see {Supported Clock
1002 /// Types} in the component documentation), the specified
1003 /// `eventSchedulerName` to be used to identify this event scheduler, and
1004 /// the specified `metricsRegistry` to be used for reporting metrics.
1005 /// If `metricsRegistry` is 0, `bdlm::MetricsRegistry::singleton()` is
1006 /// used. Optionally specify a `basicAllocator` used to supply memory.
1007 /// If `basicAllocator` is 0, the currently installed default allocator
1008 /// is used.
1010 const bsl::string_view& eventSchedulerName,
1011 bdlm::MetricsRegistry *metricsRegistry,
1012 bslma::Allocator *basicAllocator = 0);
1013
1014#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1015 /// Create an event scheduler using the default dispatcher functor (see
1016 /// {The Dispatcher Thread and the Dispatcher Functor} in the
1017 /// component-level documentation) and using the system realtime clock
1018 /// to indicate the epoch used for all time intervals. Optionally
1019 /// specify a `basicAllocator` used to supply memory. If
1020 /// `basicAllocator` is 0, the currently installed default allocator is
1021 /// used.
1022 explicit EventScheduler(
1023 const bsl::chrono::system_clock&,
1024 bslma::Allocator *basicAllocator = 0);
1025
1026 /// Create an event scheduler using the default dispatcher functor (see
1027 /// {The Dispatcher Thread and the Dispatcher Functor} in the
1028 /// component-level documentation), using the system realtime clock to
1029 /// indicate the epoch used for all time intervals, the specified
1030 /// `eventSchedulerName` to be used to identify this event scheduler, and
1031 /// the specified `metricsRegistry` to be used for reporting metrics.
1032 /// If `metricsRegistry` is 0, `bdlm::MetricsRegistry::singleton()` is
1033 /// used. Optionally specify a `basicAllocator` used to supply memory.
1034 /// If `basicAllocator` is 0, the currently installed default allocator
1035 /// is used.
1036 explicit EventScheduler(
1037 const bsl::chrono::system_clock&,
1038 const bsl::string_view& eventSchedulerName,
1039 bdlm::MetricsRegistry *metricsRegistry,
1040 bslma::Allocator *basicAllocator = 0);
1041
1042 /// Create an event scheduler using the default dispatcher functor (see
1043 /// {The Dispatcher Thread and the Dispatcher Functor} in the
1044 /// component-level documentation) and using the system monotonic clock
1045 /// to indicate the epoch used for all time intervals. Optionally
1046 /// specify a `basicAllocator` used to supply memory. If
1047 /// `basicAllocator` is 0, the currently installed default allocator is
1048 /// used.
1049 explicit EventScheduler(
1050 const bsl::chrono::steady_clock&,
1051 bslma::Allocator *basicAllocator = 0);
1052
1053 /// Create an event scheduler using the default dispatcher functor (see
1054 /// {The Dispatcher Thread and the Dispatcher Functor} in the
1055 /// component-level documentation), using the system monotonic clock to
1056 /// indicate the epoch used for all time intervals, the specified
1057 /// `eventSchedulerName` to be used to identify this event scheduler, and
1058 /// the specified `metricsRegistry` to be used for reporting metrics.
1059 /// If `metricsRegistry` is 0, `bdlm::MetricsRegistry::singleton()` is
1060 /// used. Optionally specify a `basicAllocator` used to supply memory.
1061 /// If `basicAllocator` is 0, the currently installed default allocator
1062 /// is used.
1063 explicit EventScheduler(
1064 const bsl::chrono::steady_clock&,
1065 const bsl::string_view& eventSchedulerName,
1066 bdlm::MetricsRegistry *metricsRegistry,
1067 bslma::Allocator *basicAllocator = 0);
1068#endif // defined(BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY)
1069
1070 /// Create an event scheduler using the specified `dispatcherFunctor`
1071 /// (see {The Dispatcher Thread and the Dispatcher Functor} in the
1072 /// component-level documentation) and using the system realtime clock
1073 /// to indicate the epoch used for all time intervals. Optionally
1074 /// specify a `basicAllocator` used to supply memory. If
1075 /// `basicAllocator` is 0, the currently installed default allocator is
1076 /// used.
1077 explicit EventScheduler(const Dispatcher& dispatcherFunctor,
1078 bslma::Allocator *basicAllocator = 0);
1079
1080 /// Create an event scheduler using the specified `dispatcherFunctor`
1081 /// (see {The Dispatcher Thread and the Dispatcher Functor} in the
1082 /// component-level documentation), using the system realtime clock to
1083 /// indicate the epoch used for all time intervals, the specified
1084 /// `eventSchedulerName` to be used to identify this event scheduler, and
1085 /// the specified `metricsRegistry` to be used for reporting metrics.
1086 /// If `metricsRegistry` is 0, `bdlm::MetricsRegistry::singleton()` is
1087 /// used. Optionally specify a `basicAllocator` used to supply memory.
1088 /// If `basicAllocator` is 0, the currently installed default allocator
1089 /// is used.
1090 explicit EventScheduler(const Dispatcher& dispatcherFunctor,
1091 const bsl::string_view& eventSchedulerName,
1092 bdlm::MetricsRegistry *metricsRegistry,
1093 bslma::Allocator *basicAllocator = 0);
1094
1095 /// Create an event scheduler using the specified `dispatcherFunctor`
1096 /// (see {The Dispatcher Thread and the Dispatcher Functor} in the
1097 /// component-level documentation) and using the specified `clockType`
1098 /// to indicate the epoch used for all time intervals (see {Supported
1099 /// Clock Types} in the component documentation). Optionally specify a
1100 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
1101 /// the currently installed default allocator is used.
1102 EventScheduler(const Dispatcher& dispatcherFunctor,
1104 bslma::Allocator *basicAllocator = 0);
1105
1106 /// Create an event scheduler using the specified `dispatcherFunctor`
1107 /// (see {The Dispatcher Thread and the Dispatcher Functor} in the
1108 /// component-level documentation), using the specified `clockType` to
1109 /// indicate the epoch used for all time intervals (see {Supported Clock
1110 /// Types} in the component documentation), the specified
1111 /// `eventSchedulerName` to be used to identify this event scheduler, and
1112 /// the specified `metricsRegistry` to be used for reporting metrics.
1113 /// If `metricsRegistry` is 0, `bdlm::MetricsRegistry::singleton()` is
1114 /// used. Optionally specify a `basicAllocator` used to supply memory.
1115 /// If `basicAllocator` is 0, the currently installed default allocator
1116 /// is used.
1117 EventScheduler(const Dispatcher& dispatcherFunctor,
1119 const bsl::string_view& eventSchedulerName,
1120 bdlm::MetricsRegistry *metricsRegistry,
1121 bslma::Allocator *basicAllocator = 0);
1122
1123#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1124 /// Create an event scheduler using the specified `dispatcherFunctor`
1125 /// (see {The Dispatcher Thread and the Dispatcher Functor} in the
1126 /// component-level documentation) and using the system realtime clock
1127 /// to indicate the epoch used for all time intervals. Optionally
1128 /// specify a `basicAllocator` used to supply memory. If
1129 /// `basicAllocator` is 0, the currently installed default allocator is
1130 /// used.
1131 EventScheduler(const Dispatcher& dispatcherFunctor,
1132 const bsl::chrono::system_clock&,
1133 bslma::Allocator *basicAllocator = 0);
1134
1135 /// Create an event scheduler using the specified `dispatcherFunctor`
1136 /// (see {The Dispatcher Thread and the Dispatcher Functor} in the
1137 /// component-level documentation), using the system realtime clock to
1138 /// indicate the epoch used for all time intervals, the specified
1139 /// `eventSchedulerName` to be used to identify this event scheduler, and
1140 /// the specified `metricsRegistry` to be used for reporting metrics.
1141 /// If `metricsRegistry` is 0, `bdlm::MetricsRegistry::singleton()` is
1142 /// used. Optionally specify a `basicAllocator` used to supply memory.
1143 /// If `basicAllocator` is 0, the currently installed default allocator
1144 /// is used.
1145 EventScheduler(const Dispatcher& dispatcherFunctor,
1146 const bsl::chrono::system_clock&,
1147 const bsl::string_view& eventSchedulerName,
1148 bdlm::MetricsRegistry *metricsRegistry,
1149 bslma::Allocator *basicAllocator = 0);
1150
1151 /// Create an event scheduler using the specified `dispatcherFunctor`
1152 /// (see {The Dispatcher Thread and the Dispatcher Functor} in the
1153 /// component-level documentation) and using the system monotonic clock
1154 /// to indicate the epoch used for all time intervals. Optionally
1155 /// specify a `basicAllocator` used to supply memory. If
1156 /// `basicAllocator` is 0, the currently installed default allocator is
1157 /// used.
1158 EventScheduler(const Dispatcher& dispatcherFunctor,
1159 const bsl::chrono::steady_clock&,
1160 bslma::Allocator *basicAllocator = 0);
1161
1162 /// Create an event scheduler using the specified `dispatcherFunctor`
1163 /// (see {The Dispatcher Thread and the Dispatcher Functor} in the
1164 /// component-level documentation), using the system monotonic clock to
1165 /// indicate the epoch used for all time intervals, the specified
1166 /// `eventSchedulerName` to be used to identify this event scheduler, and
1167 /// the specified `metricsRegistry` to be used for reporting metrics.
1168 /// If `metricsRegistry` is 0, `bdlm::MetricsRegistry::singleton()` is
1169 /// used. Optionally specify a `basicAllocator` used to supply memory.
1170 /// If `basicAllocator` is 0, the currently installed default allocator
1171 /// is used.
1172 EventScheduler(const Dispatcher& dispatcherFunctor,
1173 const bsl::chrono::steady_clock&,
1174 const bsl::string_view& eventSchedulerName,
1175 bdlm::MetricsRegistry *metricsRegistry,
1176 bslma::Allocator *basicAllocator = 0);
1177#endif // defined(BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY)
1178
1179 /// Discard all unprocessed events and destroy this object.
1180 ///
1181 /// \pre The behavior is undefined unless the scheduler is stopped.
1183
1184 // MANIPULATORS
1185
1186 /// Cancel all recurring and one-time events scheduled in this
1187 /// EventScheduler.
1189
1190 /// Cancel all recurring and one-time events scheduled in this
1191 /// EventScheduler. Block until all events have either been cancelled
1192 /// or dispatched before this call returns.
1193 ///
1194 /// \pre The behavior is undefined if this method is invoked from the dispatcher thread.
1196
1197 /// Cancel the event having the specified `handle`. Return 0 on
1198 /// successful cancellation, and a non-zero value if the `handle` is
1199 /// invalid *or* if the event has already been dispatched or canceled.
1200 ///
1201 /// \note Note that due to the implicit conversion from Handle types, these
1202 /// methods also match the following:
1203 /// @code
1204 /// int cancelEvent(const EventHandle& handle);
1205 /// int cancelEvent(const RecurringEventHandle& handle);
1206 /// @endcode
1207 /// Compared to the version taking a pointer to Handle, the managed
1208 /// reference to the event is not released until the Handle goes out of
1209 /// scope.
1210 int cancelEvent(const Event *handle);
1211 int cancelEvent(const RecurringEvent *handle);
1212
1213 /// Cancel the event having the specified `handle` and release the
1214 /// handle. Return 0 on successful cancellation, and a non-zero value
1215 /// if the `handle` is invalid *or* if the event has already been dispatched or canceled.
1216 ///
1217 /// \note Note that `handle` is released whether this
1218 /// call is successful or not.
1221
1222 /// Cancel the event having the specified `handle`. Block until the
1223 /// event having `handle` (if it is valid) is either successfully
1224 /// canceled or dispatched before the call returns. Return 0 on
1225 /// successful cancellation, and a non-zero value if `handle` is invalid
1226 /// *or* if the event has already been dispatched or canceled.
1227 ///
1228 /// \pre The behavior is undefined if this method is invoked from the dispatcher thread.
1229 ///
1230 /// \note Note that if the event is being executed when this method
1231 /// is invoked, this method will block until it is completed and then
1232 /// return a nonzero value.
1233 int cancelEventAndWait(const Event *handle);
1235
1236 /// Cancel the event having the specified `handle` and release
1237 /// `*handle`. Block until the event having `handle` (if it is valid)
1238 /// is either successfully canceled or dispatched before the call
1239 /// returns. Return 0 on successful cancellation, and a non-zero value
1240 /// if `handle` is invalid *or* if the event has already been dispatched or canceled.
1241 ///
1242 /// \pre The behavior is undefined if this method is invoked from the dispatcher thread.
1243 ///
1244 /// \note Note that if the event is being
1245 /// executed when this method is invoked, this method will block until
1246 /// it is completed and then return a nonzero value. Also note that it
1247 /// is guaranteed that `*handle` will be released whether this call is
1248 /// successful or not.
1251
1252 /// Release the specified `handle`. Every handle reference added by
1253 /// `scheduleEventRaw`, `addEventRefRaw`, `scheduleRecurringEventRaw`,
1254 /// or `addRecurringEventRefRaw` must be released using this method to avoid leaking resources.
1255 ///
1256 /// \pre The behavior is undefined if the value of
1257 /// `handle` is used for any purpose after being released.
1258 void releaseEventRaw(Event *handle);
1259 void releaseEventRaw(RecurringEvent *handle);
1260
1261 /// Reschedule the event referred to by the specified `handle` at the
1262 /// specified `newEpochTime` truncated to microseconds. Return 0 on
1263 /// successful reschedule, and a non-zero value if the `handle` is
1264 /// invalid *or* if the event has already been dispatched. The
1265 /// `newEpochTime` is an absolute time represented as an interval from
1266 /// some epoch, which is determined by the clock indicated at
1267 /// construction (see {Supported Clock Types} in the component
1268 /// documentation).
1269 int rescheduleEvent(const Event *handle,
1270 const bsls::TimeInterval& newEpochTime);
1271
1272#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1273 /// Reschedule the event referred to by the specified `handle` at the
1274 /// specified `newEpochTime` truncated to microseconds. Return 0 on
1275 /// successful reschedule, and a non-zero value if the `handle` is
1276 /// invalid *or* if the event has already been dispatched. The
1277 /// `newEpochTime` is an absolute time represented as an interval from
1278 /// some epoch, determined by the clock associated with the time point.
1279 template <class t_CLOCK, class t_DURATION>
1280 int rescheduleEvent(
1281 const Event *handle,
1282 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& newEpochTime);
1283#endif
1284
1285 /// Reschedule the event referred to by the specified `handle` at the
1286 /// specified `newEpochTime` truncated to microseconds. Block until the
1287 /// event having `handle` (if it is valid) is either successfully
1288 /// rescheduled or dispatched before the call returns. Return 0 on
1289 /// successful reschedule, and a non-zero value if `handle` is invalid
1290 /// *or* if the event has already been dispatched. The `newEpochTime`
1291 /// is an absolute time represented as an interval from some epoch,
1292 /// which is determined by the clock indicated at construction (see
1293 /// {Supported Clock Types} in the component documentation).
1294 ///
1295 /// \pre The behavior is undefined if this method is invoked from the dispatcher
1296 /// thread.
1298 const bsls::TimeInterval& newEpochTime);
1299
1300#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1301 /// Reschedule the event referred to by the specified `handle` at the
1302 /// specified `newEpochTime` truncated to microseconds. Block until the
1303 /// event having `handle` (if it is valid) is either successfully
1304 /// rescheduled or dispatched before the call returns. Return 0 on
1305 /// successful reschedule, and a non-zero value if `handle` is invalid
1306 /// *or* if the event has already been dispatched. The `newEpochTime`
1307 /// is an absolute time represented as an interval from some epoch,
1308 /// which is determined by the clock associated with the time point.
1309 ///
1310 /// \pre The behavior is undefined if this method is invoked from the
1311 /// dispatcher thread.
1312 template <class t_CLOCK, class t_DURATION>
1314 const Event *handle,
1315 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& newEpochTime);
1316#endif
1317
1318 /// Schedule the specified `callback` to be dispatched at the specified
1319 /// `epochTime` truncated to microseconds. Load into the optionally
1320 /// specified `event` a handle that can be used to cancel the event (by
1321 /// invoking `cancelEvent`). The `epochTime` is an absolute time
1322 /// represented as an interval from some epoch, which is determined by
1323 /// the clock indicated at construction (see {Supported Clock Types} in
1324 /// the component documentation). This method guarantees that the event
1325 /// will occur at or after `epochTime`. `epochTime` may be in the past,
1326 /// in which case the event will be executed as soon as possible.
1327 void scheduleEvent(const bsls::TimeInterval& epochTime,
1328 const bsl::function<void()>& callback);
1329 void scheduleEvent(EventHandle *event,
1330 const bsls::TimeInterval& epochTime,
1331 const bsl::function<void()>& callback);
1332
1333#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1334 /// Schedule the specified `callback` to be dispatched at the specified
1335 /// `epochTime` truncated to microseconds. Load into the optionally
1336 /// specified `event` a handle that can be used to cancel the event (by
1337 /// invoking `cancelEvent`). The `epochTime` is an absolute time
1338 /// represented as an interval from some epoch, which is determined by
1339 /// the clock associated with the time point. This method guarantees
1340 /// that the event will occur at or after `epochTime`. `epochTime` may
1341 /// be in the past, in which case the event will be executed as soon as
1342 /// possible.
1343 template <class t_CLOCK, class t_DURATION>
1344 void scheduleEvent(
1345 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& epochTime,
1346 const bsl::function<void()>& callback);
1347 template <class t_CLOCK, class t_DURATION>
1348 void scheduleEvent(
1349 EventHandle *event,
1350 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& epochTime,
1351 const bsl::function<void()>& callback);
1352#endif
1353
1354 /// Schedule the specified `callback` to be dispatched at the specified
1355 /// `epochTime` truncated to microseconds. Load into the specified
1356 /// `event` pointer a handle that can be used to cancel the event (by
1357 /// invoking `cancelEvent`). The `epochTime` is an *absolute* time
1358 /// represented as an interval from some epoch, which is determined by
1359 /// the clock indicated at construction (see {Supported Clock Types} in
1360 /// the component documentation). The `event` pointer must be released
1361 /// invoking `releaseEventRaw` when it is no longer needed.
1363 const bsls::TimeInterval& epochTime,
1364 const bsl::function<void()>& callback);
1365
1366#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1367 /// Schedule the specified `callback` to be dispatched at the specified
1368 /// `epochTime` truncated to microseconds. Load into the specified
1369 /// `event` pointer a handle that can be used to cancel the event (by
1370 /// invoking `cancelEvent`). The `epochTime` is an absolute time
1371 /// represented as an interval from some epoch, which is determined by
1372 /// the clock associated with the time point. The `event` pointer must
1373 /// be released invoking `releaseEventRaw` when it is no longer needed.
1374 template <class t_CLOCK, class t_DURATION>
1375 void scheduleEventRaw(
1376 Event **event,
1377 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& epochTime,
1378 const bsl::function<void()>& callback);
1379#endif
1380
1381 /// Schedule a recurring event that invokes the specified `callback` at
1382 /// every specified `interval` truncated to microseconds, with the first
1383 /// event dispatched at the optionally specified `startEpochTime`
1384 /// truncated to microseconds. If `startEpochTime` is not specified,
1385 /// the first event is dispatched at one `interval` from now. Load into
1386 /// the optionally specified `event` a handle that can be used to cancel
1387 /// the event (by invoking `cancelEvent`). The `startEpochTime` is an
1388 /// absolute time represented as an interval from some epoch, which is
1389 /// determined by the clock indicated at construction (see {Supported
1390 /// Clock Types} in the component documentation).
1391 ///
1392 /// \pre The behavior is undefined unless `interval` is at least one microsecond.
1393 ///
1394 /// \note Note that if `startEpochTime` is in the past, the first event is dispatched
1395 /// immediately, and additional `(now() - startEpochTime) / interval`
1396 /// events will be submitted serially.
1397 void scheduleRecurringEvent(const bsls::TimeInterval& interval,
1398 const bsl::function<void()>& callback,
1399 const bsls::TimeInterval& startEpochTime
1400 = bsls::TimeInterval(0));
1401 void scheduleRecurringEvent(RecurringEventHandle *event,
1402 const bsls::TimeInterval& interval,
1403 const bsl::function<void()>& callback,
1404 const bsls::TimeInterval& startEpochTime
1405 = bsls::TimeInterval(0));
1406
1407#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1408 /// Schedule a recurring event that invokes the specified `callback` at
1409 /// every specified `interval` truncated to microseconds, with the first
1410 /// event dispatched at the optionally specified `startEpochTime`
1411 /// truncated to microseconds. If `startEpochTime` is not specified,
1412 /// the first event is dispatched at one `interval` from now. Load into
1413 /// the optionally specified `event` a handle that can be used to cancel
1414 /// the event (by invoking `cancelEvent`). The `startEpochTime` is an
1415 /// absolute time represented as an interval from some epoch, which is
1416 /// determined by the clock associated with the time point.
1417 ///
1418 /// \pre The behavior is undefined unless `interval` is at least one microsecond.
1419 ///
1420 /// \note Note that if `startEpochTime` is in the past, the first event is
1421 /// dispatched immediately, and additional
1422 /// `(now() - startEpochTime) / interval` events will be submitted
1423 /// serially.
1424 template <class t_CLOCK,
1425 class t_REP_TYPE,
1426 class t_PERIOD_TYPE,
1427 class t_DURATION>
1428 void scheduleRecurringEvent(
1429 const bsl::chrono::duration<t_REP_TYPE,
1430 t_PERIOD_TYPE>& interval,
1431 const bsl::function<void()>& callback,
1432 const bsl::chrono::time_point<t_CLOCK,
1433 t_DURATION>& startEpochTime =
1434 t_CLOCK::now());
1435 template <class t_CLOCK,
1436 class t_REP_TYPE,
1437 class t_PERIOD_TYPE,
1438 class t_DURATION>
1439 void scheduleRecurringEvent(
1440 RecurringEventHandle *event,
1441 const bsl::chrono::duration<t_REP_TYPE,
1442 t_PERIOD_TYPE>& interval,
1443 const bsl::function<void()>& callback,
1444 const bsl::chrono::time_point<t_CLOCK,
1445 t_DURATION>& startEpochTime =
1446 t_CLOCK::now());
1447#endif
1448
1449 /// Schedule a recurring event that invokes the specified `callback` at
1450 /// every specified `interval` truncated to microseconds, with the first
1451 /// event dispatched at the optionally specified `startEpochTime`
1452 /// truncated to microseconds. If `startEpochTime` is not specified,
1453 /// the first event is dispatched at one `interval` from now. Load into
1454 /// the specified `event` pointer a handle that can be used to cancel
1455 /// the event (by invoking `cancelEvent`). The `startEpochTime` is an
1456 /// absolute time represented as an interval from some epoch, which is
1457 /// determined by the clock indicated at construction (see {Supported
1458 /// Clock Types} in the component documentation). The `event` pointer
1459 /// must be released by invoking `releaseEventRaw` when it is no longer needed.
1460 ///
1461 /// \pre The behavior is undefined unless `interval` is at least one microsecond.
1462 ///
1463 /// \note Note that if `startEpochTime` is in the past, the
1464 /// first event is dispatched immediately, and additional
1465 /// `(now() - startEpochTime) / interval` events will be submitted
1466 /// serially.
1468 RecurringEvent **event,
1469 const bsls::TimeInterval& interval,
1470 const bsl::function<void()>& callback,
1471 const bsls::TimeInterval& startEpochTime
1472 = bsls::TimeInterval(0));
1473
1474#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1475 /// Schedule a recurring event that invokes the specified `callback` at
1476 /// every specified `interval` truncated to microseconds, with the first
1477 /// event dispatched at the optionally specified `startEpochTime`
1478 /// truncated to microseconds. If `startEpochTime` is not specified,
1479 /// the first event is dispatched at one `interval` from now. Load into
1480 /// the specified `event` pointer a handle that can be used to cancel
1481 /// the event (by invoking `cancelEvent`). The `startEpochTime` is an
1482 /// absolute time represented as an interval from some epoch, which is
1483 /// determined by the clock associated with the time point. The `event`
1484 /// pointer must be released by invoking `releaseEventRaw` when it is no longer needed.
1485 ///
1486 /// \pre The behavior is undefined unless `interval` is at least one microsecond.
1487 ///
1488 /// \note Note that if `startEpochTime` is in the
1489 /// past, the first event is dispatched immediately, and additional
1490 /// `(now() - startEpochTime) / interval` events will be submitted
1491 /// serially.
1492 template <class t_CLOCK,
1493 class t_REP_TYPE,
1494 class t_PERIOD_TYPE,
1495 class t_DURATION>
1496 void scheduleRecurringEventRaw(
1497 RecurringEvent **event,
1498 const bsl::chrono::duration<t_REP_TYPE,
1499 t_PERIOD_TYPE>& interval,
1500 const bsl::function<void()>& callback,
1501 const bsl::chrono::time_point<t_CLOCK,
1502 t_DURATION>& startEpochTime =
1503 t_CLOCK::now());
1504#endif
1505
1506 /// Begin dispatching events on this scheduler using default attributes
1507 /// for the dispatcher thread. Return 0 on success, and a nonzero value
1508 /// otherwise. If another thread is currently executing `stop`, wait
1509 /// until the dispatcher thread stops before starting a new one. If
1510 /// this scheduler has already started (and is not currently being
1511 /// stopped by another thread) then this invocation has no effect and 0
1512 /// is returned. The created thread will use the `eventSchedulerName`
1513 /// supplied at construction if it is not empty, otherwise "bdl.EventSched".
1514 ///
1515 /// \pre The behavior is undefined if this method is invoked
1516 /// in the dispatcher thread (i.e., in a job executed by this scheduler).
1517 ///
1518 /// \note Note that any event whose time has already passed is pending and
1519 /// will be dispatched immediately.
1520 int start();
1521
1522 /// Begin dispatching events on this scheduler using the specified
1523 /// `threadAttributes` for the dispatcher thread (except that the
1524 /// DETACHED attribute is ignored). Return 0 on success, and a nonzero
1525 /// value otherwise. If another thread is currently executing `stop`,
1526 /// wait until the dispatcher thread stops before starting a new one.
1527 /// If this scheduler has already started (and is not currently being
1528 /// stopped by another thread) then this invocation has no effect and 0
1529 /// is returned. The created thread will use the name
1530 /// `threadAttributes.getThreadName()` if it is not empty, otherwise
1531 /// `eventSchedulerName` supplied at construction if it is not empty, otherwise "bdl.EventSched".
1532 ///
1533 /// \pre The behavior is undefined if this method
1534 /// is invoked in the dispatcher thread (i.e., in a job executed by this scheduler).
1535 ///
1536 /// \note Note that any event whose time has already passed is
1537 /// pending and will be dispatched immediately.
1538 int start(const bslmt::ThreadAttributes& threadAttributes);
1539
1540 /// End the dispatching of events on this scheduler (but do not remove
1541 /// any pending events), and wait for any (one) currently executing
1542 /// event to complete. If the scheduler is already stopped then this
1543 /// method has no effect. This scheduler can be restarted by invoking `start`.
1544 ///
1545 /// \pre The behavior is undefined if this method is invoked from
1546 /// the dispatcher thread.
1547 void stop();
1548
1549 // ACCESSORS
1550
1551 /// Increment the reference count for the event referred to by the
1552 /// specified `handle` and return `handle`. There must be a
1553 /// corresponding call to `releaseEventRaw` when the reference is no
1554 /// longer needed.
1555 Event *addEventRefRaw(Event *handle) const;
1556
1557 /// Increment the reference count for the recurring event referred to by
1558 /// the specified `handle` and return `handle`. There must be a
1559 /// corresponding call to `releaseEventRaw` when the reference is no
1560 /// longer needed.
1562
1563 /// Return the value of the clock type that this object was created
1564 /// with.
1566
1567 /// Return `true` if the calling thread is the dispatcher thread of this
1568 /// scheduler, and `false` otherwise.
1569 bool isInDispatcherThread() const;
1570
1571 /// Return `true` if a call to `start` has finished successfully more
1572 /// recently than any call to `stop`, and `false` otherwise.
1573 bool isStarted() const;
1574
1575 /// Return the current epoch time, an absolute time represented as an
1576 /// interval from some epoch, which is determined by the clock indicated
1577 /// at construction (see {Supported Clock Types} in the component
1578 /// documentation).
1579 bsls::TimeInterval now() const;
1580
1581 /// Return the number of pending one-time events in this scheduler.
1582 int numEvents() const;
1583
1584 /// Return the number of recurring events registered with this
1585 /// scheduler.
1586 int numRecurringEvents() const;
1587
1588 /// Return the earliest scheduled starting time of the pending events
1589 /// and recurring events registered with this scheduler. If there are
1590 /// no pending events or recurring events, return `INT64_MAX`
1591 /// microseconds.
1593
1594 /// Return the scheduled starting time of the event having the specified
1595 /// `handle`. If the `handle` is invalid, *or* the event has already been
1596 /// canceled, return an optional without a value.
1598 const EventHandle& handle) const;
1600 const RecurringEventHandle& handle) const;
1601
1602 // Aspects
1603
1604 /// Return the allocator used by this object to supply memory.
1605 bslma::Allocator *allocator() const;
1606};
1607
1608 // ===============================
1609 // class EventSchedulerEventHandle
1610 // ===============================
1611
1612/// Objects of this type refer to events in the `EventScheduler` API. They
1613/// are convertible to `const Event*` references and may be used in any
1614/// method that expects them.
1616{
1617
1618 // PRIVATE TYPES
1620
1621 // DATA
1622 EventQueue::PairHandle d_handle;
1623
1624 // FRIENDS
1625 friend class EventScheduler;
1626
1627 public:
1628 // PUBLIC TYPES
1630
1631 // CREATORS
1632
1633 /// Create a new handle object that does not refer to an event.
1635
1636 /// Create a new handle object referring to the same event as the
1637 /// specified `rhs` handle.
1639
1640 /// Destroy this object and release the managed reference, if any.
1642
1643 // MANIPULATORS
1644
1645 /// Release this handle's reference, if any; then make this handle refer
1646 /// to the same event as the specified `rhs` handle. Return a
1647 /// modifiable reference to this handle.
1649
1650 /// Release the reference (if any) held by this object.
1651 void release();
1652
1653 // ACCESSORS
1654
1655 /// Return a "raw" pointer to the event managed by this handle, or 0 if
1656 /// this handle does not manage a reference.
1657 operator const Event*() const;
1658};
1659
1660 // ========================================
1661 // class EventSchedulerRecurringEventHandle
1662 // ========================================
1663
1664/// Objects of this type refer to recurring events in the `EventScheduler`
1665/// API. They are convertible to `const RecurringEvent*` references and may
1666/// be used in any method which expects these.
1668{
1669
1670 // PRIVATE TYPES
1671 typedef EventScheduler::RecurringEventData RecurringEventData;
1673 RecurringEventData> RecurringEventQueue;
1674
1675 // DATA
1677
1678 // FRIENDS
1679 friend class EventScheduler;
1680
1681 public:
1682 // PUBLIC TYPES
1684
1685 // CREATORS
1686
1687 /// Create a new handle object.
1689
1690 /// Create a new handle object referring to the same recurring event as
1691 /// the specified `rhs` handle.
1693 const EventSchedulerRecurringEventHandle& original);
1694
1695 /// Destroy this object and release the managed reference, if any.
1697
1698 // MANIPULATORS
1699
1700 /// Release the reference managed by this handle, if any; then make this
1701 /// handle refer to the same recurring event as the specified `rhs`
1702 /// handle. Return a modifiable reference to this event handle.
1705
1706 /// Release the reference managed by this handle, if any.
1707 void release();
1708
1709 // ACCESSORS
1710
1711 /// Return a "raw" pointer to the recurring event managed by this
1712 /// handle, or 0 if this handle does not manage a reference.
1713 operator const RecurringEvent*() const;
1714
1715};
1716
1717 // ==================================
1718 // class EventSchedulerTestTimeSource
1719 // ==================================
1720
1721/// This class provides a means to change the clock that is used by a given
1722/// event-scheduler to determine when events should be triggered.
1723/// Constructing a `EventSchedulerTestTimeSource` alters the behavior of the
1724/// supplied event-scheduler. After a test time-source is created, the
1725/// underlying scheduler will run events according to a discrete timeline,
1726/// whose successive values are determined by calls to `advanceTime` on the
1727/// test time-source, and can be retrieved by calling `now` on that test time-source.
1728///
1729/// \note Note that the "system-time" held by a test time-source
1730/// *does* *not* correspond to the current system time. Test writers must
1731/// use caution when scheduling absolute-time events so that they are
1732/// scheduled relative to the test time-source's value for `now`.
1733///
1734/// See @ref bdlmt_eventscheduler
1736
1737 private:
1738 // DATA
1740 d_data_sp; // shared pointer to the state whose
1741 // lifetime must be as long as
1742 // `*this` and `*d_scheduler_p`
1743
1744 EventScheduler *d_scheduler_p; // pointer to the scheduler that we
1745 // are augmenting
1746
1747 public:
1748 // TRAITS
1751
1752 // CREATORS
1753
1754 /// Create a test time-source object that will control the "system-time"
1755 /// observed by the specified `scheduler`. Initialize `now` to be an arbitrary time value.
1756 ///
1757 /// \pre The behavior is undefined if any methods have
1758 /// previously been called on `scheduler`. Optionally specify a
1759 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
1760 /// the currently installed default allocator is used.
1761 ///
1762 /// \pre The behavior is undefined unless the supplied allocator also outlives the
1763 /// `EventScheduler` associated with this time source.
1764 explicit
1766 bslma::Allocator *basicAllocator = 0);
1767
1768 // MANIPULATORS
1769
1770 /// Advance this object's current-time value by the specified `amount`
1771 /// of time, notify the scheduler that the time has changed, and wait
1772 /// for the scheduler to process the events triggered by this change in
1773 /// time. Return the updated current-time value.
1774 ///
1775 /// \pre The behavior is undefined unless `amount` is positive, and `now + amount` is within
1776 /// the range that can be represented with a `bsls::TimeInterval`.
1778
1779 // ACCESSORS
1780
1781 /// Return this object's current-time value. Upon construction, this
1782 /// method will return an arbitrary value. Subsequent calls to
1783 /// `advanceTime` will adjust the arbitrary value forward.
1785};
1786
1787// ============================================================================
1788// INLINE DEFINITIONS
1789// ============================================================================
1790
1791 // -------------------------------
1792 // class EventSchedulerEventHandle
1793 // -------------------------------
1794
1795// CREATORS
1796inline
1800
1801inline
1803 const EventSchedulerEventHandle& original)
1804: d_handle(original.d_handle)
1805{
1806}
1807
1808inline
1812
1813// MANIPULATORS
1814inline
1817{
1818 d_handle = rhs.d_handle;
1819 return *this;
1820}
1821
1822inline
1824{
1825 d_handle.release();
1826}
1827} // close package namespace
1828
1829// ACCESSORS
1830
1831// The scoping of "Event" below should not be necessary, but xlc (versions 8
1832// and 9) requires it
1833inline
1834bdlmt::EventSchedulerEventHandle::
1835operator const bdlmt::EventSchedulerEventHandle::Event*() const
1836{
1837 return (const Event*)((const EventQueue::Pair*)d_handle);
1838}
1839
1840namespace bdlmt {
1841
1842 // ----------------------------------------
1843 // class EventSchedulerRecurringEventHandle
1844 // ----------------------------------------
1845
1846// CREATORS
1847inline
1851
1852inline
1858
1859inline
1863
1864// MANIPULATORS
1865inline
1867{
1868 d_handle.release();
1869}
1870
1871inline
1875{
1876 d_handle = rhs.d_handle;
1877 return *this;
1878}
1879} // close package namespace
1880
1881// ACCESSORS
1882
1883// The scoping of "RecurringEvent" below should not be necessary, but xlc
1884// (versions 8 and 9) requires it
1885inline
1886bdlmt::EventSchedulerRecurringEventHandle::operator
1888{
1889 return (const RecurringEvent*)((const RecurringEventQueue::Pair*)d_handle);
1890}
1891
1892namespace bdlmt {
1893
1894 // --------------------
1895 // class EventScheduler
1896 // --------------------
1897
1898inline
1900 *EventScheduler::castToQueuePair(const Event *handle)
1901{
1902 return reinterpret_cast<const EventQueue::Pair *>(
1903 static_cast<const void *>(handle));
1904}
1905
1906inline
1908 *EventScheduler::castToQueuePair(const RecurringEvent *handle)
1909{
1910 return reinterpret_cast<const RecurringEventQueue::Pair *>(
1911 static_cast<const void *>(handle));
1912}
1913
1914#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1915// PRIVATE CLASS METHODS
1916template <class t_CLOCK, class t_DURATION>
1917// not inline because it gets put into a bsl::function
1918bsls::Types::Int64 EventScheduler::timeUntilTrigger(
1919 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& absTime)
1920{
1921 using namespace bsl::chrono;
1922
1923 auto now = t_CLOCK::now();
1924 microseconds offset = duration_cast<microseconds>(absTime - now);
1925 // If the time to fire is less than one microsecond in the future, then
1926 // report it as 1us.
1927 return 0 == offset.count() && absTime > now
1928 ? 1
1929 : static_cast<bsls::Types::Int64>(offset.count());
1930}
1931
1932template <class t_CLOCK,
1933 class t_DURATION,
1934 class t_REP_TYPE,
1935 class t_PERIOD_TYPE>
1936// not inline because it gets put into a bsl::function
1937bsls::Types::Int64 EventScheduler::timeUntilTriggerRecurring(
1938 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& absTime,
1939 const bsl::chrono::duration<t_REP_TYPE, t_PERIOD_TYPE>& interval,
1940 int eventIndex)
1941{
1942 BSLS_ASSERT(0 <= eventIndex);
1943
1944 return timeUntilTrigger(absTime + eventIndex * interval);
1945}
1946#endif
1947
1948// MANIPULATORS
1949inline
1951{
1952 const EventQueue::Pair *itemPtr = castToQueuePair(handle);
1953
1954 int ret = d_eventQueue.remove(itemPtr);
1955 if (0 == ret) {
1956 // `d_callback` may contain event handles which are in reference cycles
1957 // which would prevent cleanup of the node and freeing of resources.
1958
1959 itemPtr->data().d_callback = 0;
1960 }
1961
1962 return ret;
1963}
1964
1965inline
1967{
1968 const RecurringEventQueue::Pair *itemPtr = castToQueuePair(handle);
1969
1970 int ret = d_recurringQueue.remove(itemPtr);
1971 if (0 == ret) {
1972 // `d_callback` may contain smart pointers which are in reference
1973 // cycles which would prevent cleanup of the node and freeing of
1974 // resources. The dispatch loop copies `d_callback`, guard this
1975 // assignment clearing it with the mutex to make sure we don't collide
1976 // with that copy.
1977
1978 bslmt::LockGuard<bslmt::Mutex> lock(&d_mutex);
1979 itemPtr->data().d_callback = 0;
1980 }
1981
1982 return ret;
1983}
1984
1985inline
1987{
1988 d_eventQueue.releaseReferenceRaw(castToQueuePair(handle));
1989}
1990
1991inline
1993{
1994 d_recurringQueue.releaseReferenceRaw(castToQueuePair(handle));
1995}
1996
1997#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
1998template <class t_CLOCK, class t_DURATION>
2000 const Event *handle,
2001 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& newEpochTime)
2002{
2003 BSLS_ASSERT(handle);
2004
2005 if (bslmt::ChronoUtil::isMatchingClock<t_CLOCK>(d_clockType)) {
2006 return rescheduleEvent(handle, newEpochTime.time_since_epoch());
2007 // RETURN
2008 }
2009
2010 const EventQueue::Pair *h = castToQueuePair(handle);
2011
2012 bool isNewTop;
2013 bslmt::LockGuard<bslmt::Mutex> lock(&d_mutex);
2014 bsls::TimeInterval offsetFromNow(newEpochTime - t_CLOCK::now());
2015
2016 if (h) {
2017 h->data().d_nowOffset = bdlf::BindUtil::bind(
2018 timeUntilTrigger<t_CLOCK, t_DURATION>,
2019 newEpochTime);
2020 }
2021
2022 int ret = d_eventQueue.updateR(h,
2023 (now() + offsetFromNow).totalMicroseconds(),
2024 &isNewTop);
2025
2026 if (0 == ret && isNewTop) {
2027 d_queueCondition.signal();
2028 }
2029 return ret;
2030}
2031
2032template <class t_CLOCK, class t_DURATION>
2034 const Event *handle,
2035 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& newEpochTime)
2036{
2037 BSLS_ASSERT(handle);
2038
2039 if (bslmt::ChronoUtil::isMatchingClock<t_CLOCK>(d_clockType)) {
2040 return rescheduleEventAndWait(handle, newEpochTime.time_since_epoch());
2041 // RETURN
2042 }
2043
2044 int ret;
2045 const EventQueue::Pair *h = castToQueuePair(handle);
2046 {
2047 bool isNewTop;
2048 bslmt::LockGuard<bslmt::Mutex> lock(&d_mutex);
2049 bsls::TimeInterval offsetFromNow(newEpochTime - t_CLOCK::now());
2050
2051 if (h) {
2052 h->data().d_nowOffset = bdlf::BindUtil::bind(
2053 timeUntilTrigger<t_CLOCK, t_DURATION>,
2054 newEpochTime);
2055 }
2056
2057 ret = d_eventQueue.updateR(h,
2058 (now() + offsetFromNow).totalMicroseconds(),
2059 &isNewTop);
2060
2061 if (0 == ret) {
2062 if (isNewTop) {
2063 d_queueCondition.signal();
2064 }
2065 if (d_currentEvent != h) {
2066 return 0; // RETURN
2067 }
2068 }
2069 }
2070
2071 // Wait until event is rescheduled or dispatched.
2072 bslmt::LockGuard<bslmt::Mutex> lock(&d_mutex);
2073 while (1) {
2074 if (d_currentEvent != h) {
2075 break;
2076 }
2077 else {
2078 d_dispatcherAwaited = true;
2079 d_iterationCondition.wait(&d_mutex);
2080 }
2081 }
2082
2083 return ret;
2084}
2085#endif
2086
2087inline
2088void EventScheduler::scheduleEvent(const bsls::TimeInterval& epochTime,
2089 const bsl::function<void()>& callback)
2090{
2091 scheduleEvent(epochTime,
2092 EventData(callback, EventScheduler::returnZero));
2093}
2094
2095inline
2096void EventScheduler::scheduleEvent(EventHandle *event,
2097 const bsls::TimeInterval& epochTime,
2098 const bsl::function<void()>& callback)
2099{
2100 scheduleEvent(event, epochTime, EventData(callback, returnZero));
2101}
2102
2103#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
2104template <class t_CLOCK, class t_DURATION>
2105inline
2106void EventScheduler::scheduleEvent(
2107 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& epochTime,
2108 const bsl::function<void()>& callback)
2109{
2110 if (bslmt::ChronoUtil::isMatchingClock<t_CLOCK>(d_clockType)) {
2111 scheduleEvent(epochTime.time_since_epoch(), callback);
2112 }
2113 else {
2114 bsls::TimeInterval offsetFromNow(epochTime - t_CLOCK::now());
2115 scheduleEvent(now() + offsetFromNow,
2116 EventData(callback,
2118 timeUntilTrigger<t_CLOCK, t_DURATION>,
2119 epochTime)));
2120 }
2121}
2122
2123template <class t_CLOCK, class t_DURATION>
2124void EventScheduler::scheduleEvent(
2125 EventHandle *event,
2126 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& epochTime,
2127 const bsl::function<void()>& callback)
2128{
2129 BSLS_ASSERT(event);
2130
2131 if (bslmt::ChronoUtil::isMatchingClock<t_CLOCK>(d_clockType)) {
2132 scheduleEvent(event, epochTime.time_since_epoch(), callback);
2133 }
2134 else {
2135 bsls::TimeInterval offsetFromNow(epochTime - t_CLOCK::now());
2136
2137 scheduleEvent(event,
2138 now() + offsetFromNow,
2139 EventData(callback,
2141 timeUntilTrigger<t_CLOCK, t_DURATION>,
2142 epochTime)));
2143 }
2144}
2145
2146template <class t_CLOCK, class t_DURATION>
2148 Event **event,
2149 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& epochTime,
2150 const bsl::function<void()>& callback)
2151{
2152 BSLS_ASSERT(event);
2153
2154 if (bslmt::ChronoUtil::isMatchingClock<t_CLOCK>(d_clockType)) {
2155 scheduleEventRaw(event, epochTime.time_since_epoch(), callback);
2156 }
2157 else {
2158 using namespace bsl::chrono;
2159
2161 duration_cast<microseconds>(epochTime.time_since_epoch()).count();
2162 if (startTime < d_cachedNow) {
2163 startTime = d_cachedNow;
2164 }
2165
2166 bool newTop;
2167 d_eventQueue.addRawR(
2168 (EventQueue::Pair **)event,
2169 startTime,
2170 EventData(
2171 callback,
2172 bdlf::BindUtil::bind(timeUntilTrigger<t_CLOCK, t_DURATION>,
2173 epochTime)),
2174 &newTop);
2175
2176 if (newTop) {
2177 bslmt::LockGuard<bslmt::Mutex> lock(&d_mutex);
2178 d_queueCondition.signal();
2179 }
2180 }
2181}
2182#endif
2183
2184inline
2185void EventScheduler::scheduleRecurringEvent(
2186 const bsls::TimeInterval& interval,
2187 const bsl::function<void()>& callback,
2188 const bsls::TimeInterval& startEpochTime)
2189{
2190 // Note that when this review is converted to an assert, the following
2191 // assert is redundant and can be removed.
2192 BSLS_REVIEW(1 <= interval.totalMicroseconds());
2193 BSLS_ASSERT(0 != interval);
2194
2195 scheduleRecurringEventRaw(0, interval, callback, startEpochTime);
2196}
2197
2198inline
2199void EventScheduler::scheduleRecurringEvent(
2200 RecurringEventHandle *event,
2201 const bsls::TimeInterval& interval,
2202 const bsl::function<void()>& callback,
2203 const bsls::TimeInterval& startEpochTime)
2204{
2205 // Note that when this review is converted to an assert, the following
2206 // assert is redundant and can be removed.
2207 BSLS_REVIEW(1 <= interval.totalMicroseconds());
2208 BSLS_ASSERT(0 != interval);
2209 BSLS_ASSERT(event);
2210
2211 scheduleRecurringEvent(
2212 event,
2213 RecurringEventData(interval, callback, returnZeroInt),
2214 startEpochTime);
2215}
2216
2217#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
2218template <class t_CLOCK,
2219 class t_REP_TYPE,
2220 class t_PERIOD_TYPE,
2221 class t_DURATION>
2222void EventScheduler::scheduleRecurringEvent(
2223 const bsl::chrono::duration<t_REP_TYPE, t_PERIOD_TYPE>& interval,
2224 const bsl::function<void()>& callback,
2225 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& startEpochTime)
2226{
2227 BSLS_ASSERT(bsl::chrono::microseconds(1) <= interval);
2228
2229 if (bslmt::ChronoUtil::isMatchingClock<t_CLOCK>(d_clockType)) {
2230 scheduleRecurringEvent(interval,
2231 callback,
2232 startEpochTime.time_since_epoch());
2233 }
2234 else {
2235 using namespace bsl::chrono;
2236
2237 bsls::TimeInterval offsetFromNow(startEpochTime - t_CLOCK::now());
2238
2239 scheduleRecurringEventRaw(
2240 0,
2241 RecurringEventData(
2242 interval,
2243 callback,
2244 bdlf::BindUtil::bind(timeUntilTriggerRecurring<t_CLOCK,
2245 t_DURATION,
2246 t_REP_TYPE,
2247 t_PERIOD_TYPE>,
2248 startEpochTime,
2249 interval,
2251 now() + offsetFromNow);
2252 }
2253}
2254
2255template <class t_CLOCK,
2256 class t_REP_TYPE,
2257 class t_PERIOD_TYPE,
2258 class t_DURATION>
2259void EventScheduler::scheduleRecurringEvent(
2260 RecurringEventHandle *event,
2261 const bsl::chrono::duration<t_REP_TYPE, t_PERIOD_TYPE>& interval,
2262 const bsl::function<void()>& callback,
2263 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& startEpochTime)
2264{
2265 BSLS_ASSERT(event);
2266 BSLS_ASSERT(bsl::chrono::microseconds(1) <= interval);
2267
2268 if (bslmt::ChronoUtil::isMatchingClock<t_CLOCK>(d_clockType)) {
2269 scheduleRecurringEvent(event,
2270 interval,
2271 callback,
2272 startEpochTime.time_since_epoch());
2273 }
2274 else {
2275 using namespace bsl::chrono;
2276
2277 bsls::TimeInterval offsetFromNow(startEpochTime - t_CLOCK::now());
2278
2279 scheduleRecurringEvent(
2280 event,
2281 RecurringEventData(
2282 interval,
2283 callback,
2284 bdlf::BindUtil::bind(timeUntilTriggerRecurring<t_CLOCK,
2285 t_DURATION,
2286 t_REP_TYPE,
2287 t_PERIOD_TYPE>,
2288 startEpochTime,
2289 interval,
2291 now() + offsetFromNow);
2292 }
2293}
2294
2295template <class t_CLOCK,
2296 class t_REP_TYPE,
2297 class t_PERIOD_TYPE,
2298 class t_DURATION>
2299void EventScheduler::scheduleRecurringEventRaw(
2300 RecurringEvent **event,
2301 const bsl::chrono::duration<t_REP_TYPE, t_PERIOD_TYPE>& interval,
2302 const bsl::function<void()>& callback,
2303 const bsl::chrono::time_point<t_CLOCK, t_DURATION>& startEpochTime)
2304{
2305 BSLS_ASSERT(event);
2306 BSLS_ASSERT(bsl::chrono::microseconds(1) <= interval);
2307
2308 if (bslmt::ChronoUtil::isMatchingClock<t_CLOCK>(d_clockType)) {
2309 scheduleRecurringEventRaw(event,
2310 interval,
2311 callback,
2312 startEpochTime.time_since_epoch());
2313 }
2314 else {
2315 using namespace bsl::chrono;
2316
2317 bsls::TimeInterval offsetFromNow(startEpochTime - t_CLOCK::now());
2318
2319 scheduleRecurringEventRaw(
2320 event,
2321 RecurringEventData(
2322 interval,
2323 callback,
2324 bdlf::BindUtil::bind(timeUntilTriggerRecurring<t_CLOCK,
2325 t_DURATION,
2326 t_REP_TYPE,
2327 t_PERIOD_TYPE>,
2328 startEpochTime,
2329 interval,
2331 now() + offsetFromNow);
2332 }
2333}
2334#endif
2335
2336// ACCESSORS
2337inline
2338EventScheduler::Event*
2340{
2341 return reinterpret_cast<Event*>(d_eventQueue.addPairReferenceRaw(
2342 castToQueuePair(handle)));
2343
2344}
2345
2346inline
2349{
2350 return reinterpret_cast<RecurringEvent*>(
2351 d_recurringQueue.addPairReferenceRaw(
2352 castToQueuePair(handle)));
2353}
2354
2355inline
2357{
2358 return d_clockType;
2359}
2360
2361inline
2363{
2364 return d_dispatcherThreadId.loadAcquire() ==
2366}
2367
2368inline
2370{
2371 return d_currentTimeFunctor();
2372}
2373
2374inline
2376{
2377 return d_eventQueue.length();
2378}
2379
2380inline
2382{
2383 return d_recurringQueue.length();
2384}
2385
2386 // Aspects
2387
2388inline
2390{
2391 return d_eventQueue.allocator();
2392}
2393
2394} // close package namespace
2395
2396
2397#endif
2398
2399// ----------------------------------------------------------------------------
2400// Copyright 2024 Bloomberg Finance L.P.
2401//
2402// Licensed under the Apache License, Version 2.0 (the "License");
2403// you may not use this file except in compliance with the License.
2404// You may obtain a copy of the License at
2405//
2406// http://www.apache.org/licenses/LICENSE-2.0
2407//
2408// Unless required by applicable law or agreed to in writing, software
2409// distributed under the License is distributed on an "AS IS" BASIS,
2410// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2411// See the License for the specific language governing permissions and
2412// limitations under the License.
2413// ----------------------------- END-OF-FILE ----------------------------------
2414
2415/** @} */
2416/** @} */
2417/** @} */
#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT)
Definition bslmf_nestedtraitdeclaration.h:231
Definition bdlcc_skiplist.h:804
int remove(const Pair *reference)
Definition bdlcc_skiplist.h:3303
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlcc_skiplist.h:3866
int length() const
Return the number of items in this list.
Definition bdlcc_skiplist.h:3513
SkipListPairHandle< bsls::Types::Int64, EventData > PairHandle
Definition bdlcc_skiplist.h:828
void addRawR(Pair **result, const KEY &key, const DATA &data, bool *newFrontFlag=0)
Definition bdlcc_skiplist.h:3216
SkipListPair< bsls::Types::Int64, RecurringEventData > Pair
Definition bdlcc_skiplist.h:827
int updateR(const Pair *reference, const KEY &newKey, bool *newFrontFlag=0, bool allowDuplicates=true)
Definition bdlcc_skiplist.h:3392
static Bind< bslmf::Nil, t_FUNC, Bind_BoundTuple0 > bind(t_FUNC func)
Definition bdlf_bind.h:1835
Definition bdlm_metricsregistry.h:306
Definition bdlm_metricsregistry.h:197
Definition bdlmt_eventscheduler.h:1616
EventSchedulerEventHandle & operator=(const EventSchedulerEventHandle &rhs)
Definition bdlmt_eventscheduler.h:1816
EventScheduler::Event Event
Definition bdlmt_eventscheduler.h:1629
EventSchedulerEventHandle()
Create a new handle object that does not refer to an event.
Definition bdlmt_eventscheduler.h:1797
~EventSchedulerEventHandle()
Destroy this object and release the managed reference, if any.
Definition bdlmt_eventscheduler.h:1809
void release()
Release the reference (if any) held by this object.
Definition bdlmt_eventscheduler.h:1823
Definition bdlmt_eventscheduler.h:1668
EventSchedulerRecurringEventHandle()
Create a new handle object.
Definition bdlmt_eventscheduler.h:1848
void release()
Release the reference managed by this handle, if any.
Definition bdlmt_eventscheduler.h:1866
~EventSchedulerRecurringEventHandle()
Destroy this object and release the managed reference, if any.
Definition bdlmt_eventscheduler.h:1860
EventScheduler::RecurringEvent RecurringEvent
Definition bdlmt_eventscheduler.h:1683
EventSchedulerRecurringEventHandle & operator=(const EventSchedulerRecurringEventHandle &rhs)
Definition bdlmt_eventscheduler.h:1873
Definition bdlmt_eventscheduler.h:1735
bsls::TimeInterval advanceTime(bsls::TimeInterval amount)
bsls::TimeInterval now() const
BSLMF_NESTED_TRAIT_DECLARATION(EventSchedulerTestTimeSource, bslma::UsesBslmaAllocator)
EventSchedulerTestTimeSource(EventScheduler *scheduler, bslma::Allocator *basicAllocator=0)
Definition bdlmt_eventscheduler.h:566
EventScheduler(bsls::SystemClockType::Enum clockType, const bsl::string_view &eventSchedulerName, bdlm::MetricsRegistry *metricsRegistry, bslma::Allocator *basicAllocator=0)
bsls::TimeInterval now() const
Definition bdlmt_eventscheduler.h:2369
int cancelEvent(RecurringEventHandle *handle)
int cancelEventAndWait(const Event *handle)
int rescheduleEvent(const Event *handle, const bsls::TimeInterval &newEpochTime)
EventScheduler(const Dispatcher &dispatcherFunctor, const bsl::string_view &eventSchedulerName, bdlm::MetricsRegistry *metricsRegistry, bslma::Allocator *basicAllocator=0)
EventScheduler(const Dispatcher &dispatcherFunctor, bsls::SystemClockType::Enum clockType, bslma::Allocator *basicAllocator=0)
bool isInDispatcherThread() const
Definition bdlmt_eventscheduler.h:2362
RecurringEvent * addRecurringEventRefRaw(RecurringEvent *handle) const
Definition bdlmt_eventscheduler.h:2348
int cancelEvent(EventHandle *handle)
int numRecurringEvents() const
Definition bdlmt_eventscheduler.h:2381
EventScheduler(bslma::Allocator *basicAllocator)
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlmt_eventscheduler.h:2389
bsls::TimeInterval nextPendingEventTime() const
int start(const bslmt::ThreadAttributes &threadAttributes)
void releaseEventRaw(Event *handle)
Definition bdlmt_eventscheduler.h:1986
EventSchedulerEventHandle EventHandle
Definition bdlmt_eventscheduler.h:717
bsl::optional< bsls::TimeInterval > scheduledEventTime(const RecurringEventHandle &handle) const
int cancelEvent(const Event *handle)
Definition bdlmt_eventscheduler.h:1950
EventScheduler(const Dispatcher &dispatcherFunctor, bslma::Allocator *basicAllocator=0)
int cancelEventAndWait(const RecurringEvent *handle)
int cancelEventAndWait(RecurringEventHandle *handle)
EventSchedulerRecurringEventHandle RecurringEventHandle
Definition bdlmt_eventscheduler.h:719
bsls::SystemClockType::Enum clockType() const
Definition bdlmt_eventscheduler.h:2356
bsl::optional< bsls::TimeInterval > scheduledEventTime(const EventHandle &handle) const
BSLMF_NESTED_TRAIT_DECLARATION(EventScheduler, bslma::UsesBslmaAllocator)
int cancelEventAndWait(EventHandle *handle)
EventScheduler(const Dispatcher &dispatcherFunctor, bsls::SystemClockType::Enum clockType, const bsl::string_view &eventSchedulerName, bdlm::MetricsRegistry *metricsRegistry, bslma::Allocator *basicAllocator=0)
EventScheduler(bsls::SystemClockType::Enum clockType, bslma::Allocator *basicAllocator=0)
EventScheduler(const bsl::string_view &eventSchedulerName, bdlm::MetricsRegistry *metricsRegistry, bslma::Allocator *basicAllocator=0)
void scheduleEventRaw(Event **event, const bsls::TimeInterval &epochTime, const bsl::function< void()> &callback)
int rescheduleEventAndWait(const Event *handle, const bsls::TimeInterval &newEpochTime)
bsl::function< void(const bsl::function< void()> &)> Dispatcher
Defines a type alias for the dispatcher functor type.
Definition bdlmt_eventscheduler.h:723
void scheduleRecurringEventRaw(RecurringEvent **event, const bsls::TimeInterval &interval, const bsl::function< void()> &callback, const bsls::TimeInterval &startEpochTime=bsls::TimeInterval(0))
bool isStarted() const
Event * addEventRefRaw(Event *handle) const
Definition bdlmt_eventscheduler.h:2339
int numEvents() const
Return the number of pending one-time events in this scheduler.
Definition bdlmt_eventscheduler.h:2375
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
Forward declaration.
Definition bslstl_function.h:946
Definition bslstl_optional.h:2043
Definition bslstl_sharedptr.h:1838
Definition bslma_allocator.h:545
Definition bslmt_condition.h:220
int wait(Mutex *mutex)
Definition bslmt_condition.h:430
void signal()
Definition bslmt_condition.h:402
Definition bslmt_lockguard.h:234
Definition bslmt_mutex.h:317
Definition bslmt_threadattributes.h:361
Definition bsls_atomic.h:896
Definition bsls_atomic.h:1205
Types::Uint64 loadAcquire() const
Definition bsls_atomic.h:2270
Definition bsls_timeinterval.h:307
BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::Types::Int64 totalMicroseconds() const
Definition bsls_timeinterval.h:1472
#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
#define BSLS_REVIEW(X)
Definition bsls_review.h:1019
const PlaceHolder< 1 > _1
Definition bdlmt_eventscheduler.h:550
Definition bdlmt_eventscheduler.h:709
Definition bdlmt_eventscheduler.h:715
Definition bslma_usesbslmaallocator.h:344
Imp::Handle Handle
Definition bslmt_threadutil.h:389
static bsls::Types::Uint64 selfIdAsUint64()
Definition bslmt_threadutil.h:1187
Enum
Definition bsls_systemclocktype.h:119
long long Int64
Definition bsls_types.h:134