Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a420f67

Browse files
committed
Merge branch 'master' of https://github.com/taskflow/taskflow
2 parents cd62b6f + fdc2d7d commit a420f67

File tree

11 files changed

+660
-1
lines changed

11 files changed

+660
-1
lines changed

CMakeLists.txt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ find_package(Threads REQUIRED)
215215
# -----------------------------------------------------------------------------
216216

217217
add_library(${PROJECT_NAME} INTERFACE)
218-
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_14)
218+
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17)
219219
target_link_libraries(${PROJECT_NAME} INTERFACE Threads::Threads)
220220
target_include_directories(${PROJECT_NAME} INTERFACE
221221
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
@@ -258,11 +258,26 @@ target_link_libraries(
258258
fibonacci ${PROJECT_NAME} tf::default_settings
259259
)
260260

261+
add_executable(condition_dsl ${TF_EXAMPLE_DIR}/condition_dsl.cpp)
262+
target_link_libraries(
263+
condition_dsl ${PROJECT_NAME} tf::default_settings
264+
)
265+
261266
add_executable(condition ${TF_EXAMPLE_DIR}/condition.cpp)
262267
target_link_libraries(
263268
condition ${PROJECT_NAME} tf::default_settings
264269
)
265270

271+
add_executable(simple_dsl ${TF_EXAMPLE_DIR}/simple_dsl.cpp)
272+
target_link_libraries(
273+
simple_dsl ${PROJECT_NAME} tf::default_settings
274+
)
275+
276+
add_executable(visualization_dsl ${TF_EXAMPLE_DIR}/visualization_dsl.cpp)
277+
target_link_libraries(
278+
visualization_dsl ${PROJECT_NAME} tf::default_settings
279+
)
280+
266281
add_executable(visualization ${TF_EXAMPLE_DIR}/visualization.cpp)
267282
target_link_libraries(
268283
visualization ${PROJECT_NAME} tf::default_settings

examples/condition_dsl.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// 2020/08/28 - Created by netcan: https://github.com/netcan
2+
// Task DSL demo
3+
// The example creates the following cyclic graph:
4+
//
5+
// A
6+
// |
7+
// v
8+
// B<---|
9+
// | |
10+
// v |
11+
// C----|
12+
// |
13+
// v
14+
// D
15+
//
16+
// - A is a task that initializes a counter to zero
17+
// - B is a task that increments the counter
18+
// - C is a condition task that loops around B until the counter
19+
// reaches a breaking number
20+
// - D is a task that wraps up the result
21+
#include <taskflow/taskflow.hpp>
22+
#include <taskflow/dsl/task_dsl.hpp>
23+
24+
int main() {
25+
tf::Executor executor;
26+
tf::Taskflow taskflow("Conditional Tasking Demo");
27+
28+
int counter; // owner
29+
30+
// use context to pass args
31+
// context must copyable
32+
struct Context {
33+
int &rcounter; // use counter(borrow)
34+
} context{counter};
35+
36+
def_task((A, Context), {
37+
std::cout << "initializes the counter to zero\n";
38+
rcounter = 0;
39+
});
40+
def_task((B, Context), {
41+
std::cout << "loops to increment the counter\n";
42+
rcounter++;
43+
});
44+
def_task((C, Context), {
45+
std::cout << "counter is " << rcounter << " -> ";
46+
if (rcounter != 5) {
47+
std::cout << "loops again (goes to B)\n";
48+
return 0;
49+
}
50+
std::cout << "breaks the loop (goes to D)\n";
51+
return 1;
52+
});
53+
def_task((D, Context), {
54+
std::cout << "done with counter equal to " << rcounter << '\n';
55+
});
56+
57+
auto tasks = taskbuild(
58+
task(A)
59+
-> task(B)
60+
-> task(C),
61+
task(C)
62+
-> fork(B, D)
63+
)(taskflow, context);
64+
65+
tasks.get_task<A>().name("A");
66+
tasks.get_task<B>().name("B");
67+
tasks.get_task<C>().name("C");
68+
tasks.get_task<D>().name("D");
69+
70+
// visualizes the taskflow
71+
taskflow.dump(std::cout);
72+
73+
// executes the taskflow
74+
executor.run(taskflow).wait();
75+
76+
assert(counter == 5);
77+
78+
return 0;
79+
}

examples/simple_dsl.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// 2020/08/28 - Created by netcan: https://github.com/netcan
2+
// A simple example to capture the following task dependencies.
3+
// using Task DSL to describe
4+
// TaskA -> fork(TaskB, TaskC) -> TaskD
5+
#include <taskflow/taskflow.hpp> // the only include you need
6+
#include <taskflow/dsl/task_dsl.hpp> // for support dsl
7+
8+
int main() {
9+
tf::Executor executor;
10+
tf::Taskflow taskflow("simple");
11+
def_task((A), { std::cout << "TaskA\n"; });
12+
def_task((B), { std::cout << "TaskB\n"; });
13+
def_task((C), { std::cout << "TaskC\n"; });
14+
def_task((D), { std::cout << "TaskD\n"; });
15+
16+
taskbuild( // +---+
17+
task(A) // +---->| B |-----+
18+
->fork(B, C) // | +---+ |
19+
->task(D) // +---+ +-v-+
20+
)(taskflow); // | A | | D |
21+
// +---+ +-^-+
22+
// | +---+ |
23+
// +---->| C |-----+
24+
// +---+
25+
26+
executor.run(taskflow).wait();
27+
return 0;
28+
}

examples/visualization_dsl.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// 2020/08/28 - Created by netcan: https://github.com/netcan
2+
// This example demonstrates how to use 'dump' method to inspect
3+
// a taskflow graph.
4+
// use task dsl
5+
#include <taskflow/taskflow.hpp>
6+
#include <taskflow/dsl/task_dsl.hpp> // for support dsl
7+
8+
int main() {
9+
tf::Taskflow tf("Visualization Demo");
10+
11+
// ------------------------------------------------------
12+
// Static Tasking
13+
// ------------------------------------------------------
14+
def_task((A), { std::cout << "TaskA\n"; };);
15+
def_task((B), { std::cout << "TaskB\n"; };);
16+
def_task((C), { std::cout << "TaskC\n"; };);
17+
def_task((D), { std::cout << "TaskD\n"; };);
18+
def_task((E), { std::cout << "TaskE\n"; };);
19+
20+
auto tasks = taskbuild(
21+
task(A)
22+
-> fork(B, C)
23+
-> task(D),
24+
merge(A, B)
25+
-> task(E)
26+
)(tf);
27+
28+
std::cout << "[dump without name assignment]\n";
29+
tf.dump(std::cout);
30+
31+
std::cout << "[dump with name assignment]\n";
32+
tasks.get_task<A>().name("A");
33+
tasks.get_task<B>().name("B");
34+
tasks.get_task<C>().name("C");
35+
tasks.get_task<D>().name("D");
36+
tasks.get_task<E>().name("E");
37+
tf.dump(std::cout);
38+
39+
// ------------------------------------------------------
40+
// Dynamic Tasking
41+
// ------------------------------------------------------
42+
43+
return 0;
44+
}

taskflow/dsl/connection.hpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// 2020/08/28 - Created by netcan: https://github.com/netcan
2+
#pragma once
3+
#include "../core/flow_builder.hpp"
4+
#include "task_trait.hpp"
5+
#include "tuple_utils.hpp"
6+
#include "type_list.hpp"
7+
8+
namespace tf {
9+
namespace dsl {
10+
template <typename F, typename T> class Connection {
11+
using FROMs = typename TaskTrait<F>::TaskList;
12+
using TOs = typename TaskTrait<T>::TaskList;
13+
14+
public:
15+
using FromTaskList = Unique_t<Flatten_t<FROMs>>;
16+
using ToTaskList = Unique_t<Flatten_t<TOs>>;
17+
};
18+
19+
template <typename T, typename OUT = TypeList<>> struct Chain;
20+
21+
template <typename F, typename OUT> struct Chain<auto (*)(F)->void, OUT> {
22+
using From = F;
23+
using type = OUT;
24+
};
25+
26+
template <typename F, typename T, typename OUT>
27+
struct Chain<auto (*)(F)->T, OUT> {
28+
private:
29+
using To = typename Chain<T, OUT>::From;
30+
31+
public:
32+
using From = F;
33+
using type = typename Chain<
34+
T, typename OUT::template appendTo<Connection<From, To>>>::type;
35+
};
36+
37+
template <typename FROM, typename TO> struct OneToOneLink {
38+
template <typename TasksCB> struct InstanceType {
39+
constexpr void build(TasksCB &tasksCb) {
40+
constexpr size_t TasksCBSize = std::tuple_size<TasksCB>::value;
41+
constexpr size_t FromTaskIndex =
42+
TupleElementByF_v<TasksCB, IsTask<FROM>::template apply>;
43+
constexpr size_t ToTaskIndex =
44+
TupleElementByF_v<TasksCB, IsTask<TO>::template apply>;
45+
static_assert(FromTaskIndex < TasksCBSize && ToTaskIndex < TasksCBSize,
46+
"fatal: not find TaskCb in TasksCB");
47+
std::get<FromTaskIndex>(tasksCb).task_.precede(
48+
std::get<ToTaskIndex>(tasksCb).task_);
49+
}
50+
};
51+
};
52+
} // namespace dsl
53+
}; // namespace tf

taskflow/dsl/meta_macro.hpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// 2020/08/30 - Created by netcan: https://github.com/netcan
2+
// ref https://github.com/Erlkoenig90/map-macro/
3+
#pragma once
4+
#ifdef _MSC_VER
5+
#define TF_EMPTY()
6+
#define TF_GET_ARG_COUNT_(...) \
7+
TF_PASTE(TF_GET_ARG_COUNT_I(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, \
8+
55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, \
9+
43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, \
10+
31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
11+
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, \
12+
6, 5, 4, 3, 2, 1, 0, ), \
13+
TF_EMPTY())
14+
15+
#else
16+
#define TF_GET_ARG_COUNT_(...) \
17+
TF_GET_ARG_COUNT_I(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, \
18+
53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
19+
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, \
20+
25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, \
21+
11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, )
22+
#endif
23+
24+
#define TF_GET_ARG_COUNT(...) TF_GET_ARG_COUNT_(__dummy__, ##__VA_ARGS__)
25+
#define TF_GET_ARG_COUNT_I( \
26+
e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, \
27+
e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, \
28+
e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, \
29+
e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, \
30+
e62, e63, e64, size, ...) \
31+
size
32+
33+
#define TF_GET_FIRST(a, ...) a
34+
#define TF_GET_SECOND(a, b, ...) b
35+
#define TF_CONCATE(x, y) x##y
36+
#define TF_PASTE(x, y) TF_CONCATE(x, y)
37+
38+
#define TF_EVAL0(...) __VA_ARGS__
39+
#define TF_EVAL1(...) TF_EVAL0(TF_EVAL0(TF_EVAL0(__VA_ARGS__)))
40+
#define TF_EVAL2(...) TF_EVAL1(TF_EVAL1(TF_EVAL1(__VA_ARGS__)))
41+
#define TF_EVAL3(...) TF_EVAL2(TF_EVAL2(TF_EVAL2(__VA_ARGS__)))
42+
#define TF_EVAL4(...) TF_EVAL3(TF_EVAL3(TF_EVAL3(__VA_ARGS__)))
43+
#define TF_EVAL5(...) TF_EVAL4(TF_EVAL4(TF_EVAL4(__VA_ARGS__)))
44+
45+
#ifdef _MSC_VER
46+
// MSVC needs more evaluations
47+
#define TF_EVAL6(...) TF_EVAL5(TF_EVAL5(TF_EVAL5(__VA_ARGS__)))
48+
#define TF_EVAL(...) TF_EVAL6(TF_EVAL6(__VA_ARGS__))
49+
#else
50+
#define TF_EVAL(...) TF_EVAL5(__VA_ARGS__)
51+
#endif
52+
53+
#define TF_MAP_END(...)
54+
#define TF_MAP_OUT
55+
56+
#define EMPTY()
57+
#define DEFER(id) id EMPTY()
58+
59+
#define TF_MAP_GET_END2() 0, TF_MAP_END
60+
#define TF_MAP_GET_END1(...) TF_MAP_GET_END2
61+
#define TF_MAP_GET_END(...) TF_MAP_GET_END1
62+
#define TF_MAP_NEXT0(test, next, ...) next TF_MAP_OUT
63+
#define TF_MAP_NEXT1(test, next) DEFER(TF_MAP_NEXT0)(test, next, 0)
64+
#define TF_MAP_NEXT(test, next) TF_MAP_NEXT1(TF_MAP_GET_END test, next)
65+
66+
#define TF_MAP0(f, x, peek, ...) \
67+
f(x) DEFER(TF_MAP_NEXT(peek, TF_MAP1))(f, peek, __VA_ARGS__)
68+
#define TF_MAP1(f, x, peek, ...) \
69+
f(x) DEFER(TF_MAP_NEXT(peek, TF_MAP0))(f, peek, __VA_ARGS__)
70+
71+
#define TF_MAP(f, ...) \
72+
TF_EVAL(TF_MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))

taskflow/dsl/task_analyzer.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// 2020/08/28 - Created by netcan: https://github.com/netcan
2+
#pragma once
3+
#include "connection.hpp"
4+
#include "type_list.hpp"
5+
#include <type_traits>
6+
7+
namespace tf {
8+
namespace dsl {
9+
template <typename... Links> class TaskAnalyzer {
10+
template <typename FROMs, typename TOs, typename = void>
11+
struct BuildOneToOneLink;
12+
13+
template <typename... Fs, typename Ts>
14+
struct BuildOneToOneLink<TypeList<Fs...>, Ts> {
15+
using type = Concat_t<typename BuildOneToOneLink<Fs, Ts>::type...>;
16+
};
17+
18+
template <typename F, typename... Ts>
19+
struct BuildOneToOneLink<F, TypeList<Ts...>,
20+
std::enable_if_t<!IsTypeList_v<F>>> {
21+
using type = TypeList<OneToOneLink<F, Ts>...>;
22+
};
23+
24+
template <typename Link> class OneToOneLinkSetF {
25+
using FromTaskList = typename Link::FromTaskList;
26+
using ToTaskList = typename Link::ToTaskList;
27+
28+
public:
29+
using type = typename BuildOneToOneLink<FromTaskList, ToTaskList>::type;
30+
};
31+
32+
public:
33+
using AllTasks = Unique_t<
34+
Concat_t<typename Links::FromTaskList..., typename Links::ToTaskList...>>;
35+
using OneToOneLinkSet =
36+
Unique_t<Flatten_t<Map_t<TypeList<Links...>, OneToOneLinkSetF>>>;
37+
};
38+
39+
} // namespace dsl
40+
} // namespace tf

0 commit comments

Comments
 (0)