Skip to content

Commit c061dec

Browse files
merge with chun-xun
1 parent f79e27d commit c061dec

File tree

4 files changed

+38
-20
lines changed

4 files changed

+38
-20
lines changed

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ tf.linearize(A, B, C, D); // A runs before B, B runs before C, and C runs befor
154154

155155
## Step 3: Execute the Tasks
156156

157-
There are three methods to carry out a task dependency graph, `dispatch`, `silent_dispatch`, and `wait_for_all`.
157+
There are three methods to carry out a task dependency graph,
158+
`dispatch`, `silent_dispatch`, and `wait_for_all`.
158159

159160
```cpp
160161
auto future = tf.dispatch(); // non-blocking, returns with a future immediately.
@@ -572,7 +573,7 @@ auto [S, T] = tf.transform_reduce(v.begin(), v.end(), min,
572573

573574
By default, all reduce methods distribute the workload evenly across threads.
574575

575-
### *dispatch/silent_dispatch/wait_for_all*
576+
### *dispatch/silent_dispatch/wait_for_topologies/wait_for_all*
576577
Dispatching a taskflow graph will schedule threads to execute the current graph and return immediately.
577578
The method `dispatch` gives you a future object to probe the execution progress while
578579
`silent_dispatch` doesn't.
@@ -586,13 +587,22 @@ future.get();
586587
std::cout << "all tasks complete" << '\n';
587588
```
588589

589-
If you need to block your program flow until all tasks finish, use `wait_for_all` instead.
590+
If you need to block your program flow until all tasks finish
591+
(including the present taskflow graph), use `wait_for_all` instead.
590592

591593
```cpp
592594
tf.wait_for_all();
593595
std::cout << "all tasks complete" << '\n';
594596
```
595597

598+
If you only need to block your program flow until all dispatched taskflow graphs finish,
599+
use `wait_for_topologies`.
600+
601+
```cpp
602+
tf.wait_for_topologies();
603+
std::cout << "all topologies complete" << '\n';
604+
```
605+
596606
## Task API
597607

598608
Each `tf::Taskflow::Task` object is a lightweight handle for you to create dependencies in its associated graph.

doc/faq.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ If you cannot find a solution here, please post an issue [here][Github issues].
55

66
## General Questions
77

8-
### Q: How many tasks can Cpp-Taskflow handle?
8+
#### Q: How many tasks can Cpp-Taskflow handle?
99

1010
**A:** Cpp-Taskflow is a very lightweight and efficient tasking library.
1111
It has been applied in many academic and industry projects to scale up their existing workload.
1212
A research project [OpenTimer][OpenTimer] has used Cpp-Taskflow to deal with hundreds of millions of tasks.
1313

14-
### Q: What are the differences between Cpp-Taskflow and other tasking libraries?
14+
#### Q: What are the differences between Cpp-Taskflow and other tasking libraries?
1515

1616
**A:** From our humble opinion, Cpp-Taskflow is superior in its tasking API, interface, and performance.
1717
In most cases, users can quickly master Cpp-Taskflow to create large and complex dependency graphs
@@ -21,12 +21,12 @@ Of course, the judge is always left for users -:)
2121

2222
## Compile Issues
2323

24-
### Q: I can't get Cpp-Taskflow compiled in my project!
24+
#### Q: I can't get Cpp-Taskflow compiled in my project!
2525

2626
**A:** Please make sure your compile supports the latest version of C++17.
2727
Make sure your project meets the System Requirements described at [README][README].
2828

29-
### Q: Clang can't compile due to the use of std::variant.
29+
#### Q: Clang can't compile due to the use of std::variant.
3030

3131
**A:** Cpp-Taskflow uses `std::variant` to enable uniform interface between static and dynamic tasking.
3232
However it has been reported in
@@ -47,7 +47,7 @@ For clang users, you will need to use this patch in `taskflow.hpp` as follows:
4747

4848
## Programming Questions
4949

50-
### Q: What is the difference between Cpp-Taskflow threads and workers?
50+
#### Q: What is the difference between Cpp-Taskflow threads and workers?
5151

5252
**A:** The master thread owns the thread pool and can spawn workers to run tasks
5353
or shutdown the pool.
@@ -60,7 +60,11 @@ tf::Taskflow(N); // N workers, N+1 threads in the program.
6060
6161
If there is no worker threads in the pool, the master thread will do all the works by itself.
6262
63-
### Q: My program hangs and never returns after dispatching a taskflow graph.
63+
#### Q: Is taskflow thread-safe?
64+
**A:** No, the taskflow object is not thread-safe. You can't create tasks from multiple threads
65+
at the same time.
66+
67+
#### Q: My program hangs and never returns after dispatching a taskflow graph. What's wrong?
6468
6569
**A:** When the program hangs forever it is very likely your taskflow graph has a cycle.
6670
Try the `dump` method to debug the graph before dispatching your taskflow graph.

taskflow/taskflow.hpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -979,16 +979,20 @@ auto BasicFlowBuilder<NodeType>::emplace(C&& c) {
979979
auto fu = p.get_future();
980980

981981
if constexpr(std::is_same_v<void, R>) {
982-
auto& node = _nodes.emplace_front([p = MoC(std::move(p)), c = std::forward<C>(c)]() mutable {
983-
c();
984-
p.get().set_value();
985-
});
982+
auto& node = _nodes.emplace_front(
983+
[p=MoC(std::move(p)), c=std::forward<C>(c)]() mutable {
984+
c();
985+
p.get().set_value();
986+
}
987+
);
986988
return std::make_pair(TaskType(node), std::move(fu));
987989
}
988990
else {
989-
auto& node = _nodes.emplace_front([p = MoC(std::move(p)), c = std::forward<C>(c)]() mutable {
990-
p.get().set_value(c());
991-
});
991+
auto& node = _nodes.emplace_front(
992+
[p=MoC(std::move(p)), c=std::forward<C>(c)]() mutable {
993+
p.get().set_value(c());
994+
}
995+
);
992996
return std::make_pair(TaskType(node), std::move(fu));
993997
}
994998
}

unittest/taskflow.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
// --------------------------------------------------------
1414
TEST_CASE("Taskflow.Builder" * doctest::timeout(5)){
1515

16-
constexpr auto num_workers = 4;
17-
constexpr auto num_tasks = 100;
16+
auto num_workers = 4;
17+
auto num_tasks = 100;
1818

1919
tf::Taskflow tf(num_workers);
2020
REQUIRE(tf.num_workers() == num_workers);
@@ -181,8 +181,8 @@ TEST_CASE("Taskflow.Dispatch" * doctest::timeout(5)) {
181181

182182
using namespace std::chrono_literals;
183183

184-
constexpr auto num_workers = 4;
185-
constexpr auto num_tasks = 100;
184+
auto num_workers = 4;
185+
auto num_tasks = 100;
186186

187187
tf::Taskflow tf(num_workers);
188188
REQUIRE(tf.num_workers() == num_workers);

0 commit comments

Comments
 (0)