You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Applications must not use this object if this->operator bool() is false.
530
529
*/
531
-
operator bool() const noexcept;
530
+
explicit operator bool() const noexcept;
532
531
533
532
/*
534
533
Queries the status of *this.
@@ -877,7 +876,7 @@ class share_result {
877
876
Returns true if this is a non-empty shared-result.
878
877
Applications must not use this object if this->operator bool() is false.
879
878
*/
880
-
operator bool() const noexcept;
879
+
explicit operator bool() const noexcept;
881
880
882
881
/*
883
882
Queries the status of *this.
@@ -1112,12 +1111,12 @@ Regular timers have four properties that define them:
1112
1111
4. Frequency - from the time the timer was scheduled to run for the first time, the interval in milliseconds the callable will be scheduled to run periodically, until the timer is destructed or cancelled.
1113
1112
1114
1113
Like other objects in concurrencpp, timers are a move only type that can be empty.
1115
-
When a timer is destructed or `timer::cancel` is called, the timer cancels its scheduled but not yet executed tasks. Ongoing tasks are uneffected. The timer callable must be thread safe. It is recommended to set the due time and the frequency of a timer to a granularity of 50 milliseconds.
1114
+
When a timer is destructed or `timer::cancel` is called, the timer cancels its scheduled but not yet executed tasks. Ongoing tasks are uneffected. The timer callable must be thread safe. It is recommended to set the due time and the frequency of timers to a granularity of 50 milliseconds.
1116
1115
1117
1116
A timer queue is a concurrencpp worker that manages a collection of timers and processes them in just one thread of execution. It is also the agent used to create new timers.
1118
1117
When a timer deadline (whether it is the timer's due-time or frequency) has reached, the timer queue "fires" the timer by scheduling its callable to run on the associated executor as a task.
1119
1118
1120
-
Just like executors, timer queues also adhere to the RAII concept. When the runtime object gets out of scope, It shuts down the timer queue, cancelling all pending timers. After a timer queue has been shut down, any subsequent call to `make_timer`, `make_onshot_timer` and `make_delay_object` will throw an `errors::timer_queue_shutdown` exception.
1119
+
Just like executors, timer queues also adhere to the RAII concept. When the runtime object gets out of scope, It shuts down the timer queue, cancelling all pending timers. After a timer queue has been shut down, any subsequent call to `make_timer`, `make_onshot_timer` and `make_delay_object` will throw an `errors::runtime_shutdown` exception.
1121
1120
Applications must not try to shut down timer queues by themselves.
1122
1121
1123
1122
#### `timer_queue` API:
@@ -1132,7 +1131,7 @@ class timer_queue {
1132
1131
Shuts down this timer_queue:
1133
1132
Tells the underlying thread of execution to quit and joins it.
1134
1133
Cancels all pending timers.
1135
-
After this call, invocation of any method besides shutdown and shutdown_requested will throw an errors::timer_queue_shutdown.
1134
+
After this call, invocation of any method besides shutdown and shutdown_requested will throw an errors::runtime_shutdown.
1136
1135
If shutdown had been called before, this method has no effect.
1137
1136
*/
1138
1137
void shutdown() noexcept;
@@ -1145,7 +1144,7 @@ class timer_queue {
1145
1144
/*
1146
1145
Creates a new running timer where *this is the associated timer_queue.
1147
1146
Throws std::invalid_argument if executor is null.
1148
-
Throws errors::timer_queue_shutdown if shutdown had been called before.
1147
+
Throws errors::runtime_shutdown if shutdown had been called before.
1149
1148
*/
1150
1149
template<class callable_type, class ... argumet_types>
1151
1150
timer make_timer(
@@ -1158,7 +1157,7 @@ class timer_queue {
1158
1157
/*
1159
1158
Creates a new one-shot timer where *this is the associated timer_queue.
1160
1159
Throws std::invalid_argument if executor is null.
1161
-
Throws errors::timer_queue_shutdown if shutdown had been called before.
1160
+
Throws errors::runtime_shutdown if shutdown had been called before.
1162
1161
*/
1163
1162
template<class callable_type, class ... argumet_types>
1164
1163
timer make_one_shot_timer(
@@ -1170,7 +1169,7 @@ class timer_queue {
1170
1169
/*
1171
1170
Creates a new delay object where *this is the associated timer_queue.
1172
1171
Throws std::invalid_argument if executor is null.
1173
-
Throws errors::timer_queue_shutdown if shutdown had been called before.
1172
+
Throws errors::runtime_shutdown if shutdown had been called before.
1174
1173
*/
1175
1174
result<void> make_delay_object(
1176
1175
std::chrono::milliseconds due_time,
@@ -1249,7 +1248,7 @@ class timer {
1249
1248
Returns true is *this is not an empty timer, false otherwise.
1250
1249
The timer should not be used if this->operator bool() is false.
1251
1250
*/
1252
-
operator bool() const noexcept;
1251
+
explicit operator bool() const noexcept;
1253
1252
};
1254
1253
```
1255
1254
@@ -1346,7 +1345,7 @@ In this example, we created a coroutine (that does not marshal any result or thr
1346
1345
1347
1346
The concurrencpp runtime object is the agent used to acquire, store and create new executors.
1348
1347
The runtime must be created as a value type as soon as the main function starts to run.
1349
-
When the concurrencpp runtime gets out of scope, it iterates over its stored executors and shuts them down one by one by calling `executor::shutdown`. Executors then exit their inner work loop and any subsequent attempt to schedule a new task will throw a `concurrencpp::executor_shutdown` exception. The runtime also contains the global timer queue used to create timers and delay objects.
1348
+
When the concurrencpp runtime gets out of scope, it iterates over its stored executors and shuts them down one by one by calling `executor::shutdown`. Executors then exit their inner work loop and any subsequent attempt to schedule a new task will throw a `concurrencpp::runtime_shutdown` exception. The runtime also contains the global timer queue used to create timers and delay objects.
1350
1349
Upon destruction, stored executors will destroy unexecuted tasks, and wait for ongoing tasks to finish. If an ongoing task tries to use an executor to spawn new tasks or schedule its own task continuation - an exception will be thrown. In this case, ongoing tasks need to quit as soon as possible, allowing their underlying executors to quit. The timer queue will also be shut down, cancelling all running timers. With this RAII style of code, no tasks can be processed before the creation of the runtime object, and while/after the runtime gets out of scope.
1351
1350
This frees concurrent applications from needing to communicate termination messages explicitly. Tasks are free use executors as long as the runtime object is alive.
1352
1351
@@ -1435,7 +1434,7 @@ New executors can be created using `runtime::make_executor`. Applications must n
1435
1434
Another important point is to handle shutdown correctly: `shutdown`, `shutdown_requested` and `enqueue` should all monitor the executor state and behave accordingly when invoked:
1436
1435
* `shutdown` should tell underlying threads to quit and then join them.
1437
1436
* `shutdown` might be called multiple times, and the method must handle this scenario by ignoring any subsequent call to `shutdown` after the first invocation.
1438
-
* `enqueue` must throw a `concurrencpp::errors::executor_shutdown` exception if `shutdown` had been called before.
1437
+
* `enqueue` must throw a `concurrencpp::errors::runtime_shutdown` exception if `shutdown` had been called before.
1439
1438
1440
1439
Implementing an executor is one of the rare cases applications need to work with `concurrencpp::task` class directly. `concurrencpp::task` is a `std::function` like object, but with a few differences.
1441
1440
Like `std::function`, the task object stores a callable that acts as the asynchronous operation.
@@ -1501,7 +1500,7 @@ Task objects apply the short-buffer-optimization (sbo) for regular, small callab
1501
1500
/*
1502
1501
Returns true if *this stores a callable. false otherwise.
1503
1502
*/
1504
-
operator bool() const noexcept;
1503
+
expliit operator bool() const noexcept;
1505
1504
1506
1505
/*
1507
1506
Returns true if *this stores a callable,
@@ -1571,7 +1570,7 @@ public:
1571
1570
1572
1571
std::unique_lock<std::mutex> lock(_lock);
1573
1572
if (_shutdown_requested) {
1574
-
throw concurrencpp::errors::executor_shutdown("logging executor - executor was shutdown.");
1573
+
throw concurrencpp::errors::runtime_shutdown("logging executor - executor was shutdown.");
1575
1574
}
1576
1575
1577
1576
_queue.emplace(std::move(task));
@@ -1583,7 +1582,7 @@ public:
1583
1582
1584
1583
std::unique_lock<std::mutex> lock(_lock);
1585
1584
if (_shutdown_requested) {
1586
-
throw concurrencpp::errors::executor_shutdown("logging executor - executor was shutdown.");
1585
+
throw concurrencpp::errors::runtime_shutdown("logging executor - executor was shutdown.");
1587
1586
}
1588
1587
1589
1588
for (auto& task : tasks) {
@@ -1636,3 +1635,47 @@ In this example, we created an executor which logs actions like enqueuing a task
1636
1635
1637
1636
***Operating systems:** Linux, macOS, Windows (Windows 10 and above)
1638
1637
***Compilers:** MSVC (Visual Studio 2019 version 16.8.2 and above), Clang (Clang-11 and above)
1638
+
***Tools:** CMake (3.16 and above)
1639
+
1640
+
### Building, installing and testing
1641
+
1642
+
##### Building the library on Windows (release mode)
0 commit comments