1// REQUIRES: ompx_taskgraph
2// RUN: %libomp-cxx-compile-and-run
3#include <iostream>
4#include <fstream>
5#include <sstream>
6#include <cassert>
7
8// Compiler-generated code (emulation)
9typedef struct ident {
10 void* dummy;
11} ident_t;
12
13#ifdef __cplusplus
14extern "C" {
15 int __kmpc_global_thread_num(ident_t *);
16 int __kmpc_start_record_task(ident_t *, int, int, int);
17 void __kmpc_end_record_task(ident_t *, int, int , int);
18}
19#endif
20
21void func(int *num_exec) {
22 #pragma omp atomic
23 (*num_exec)++;
24}
25
26std::string tdg_string= "digraph TDG {\n"
27" compound=true\n"
28" subgraph cluster {\n"
29" label=TDG_0\n"
30" 0[style=bold]\n"
31" 1[style=bold]\n"
32" 2[style=bold]\n"
33" 3[style=bold]\n"
34" }\n"
35" 0 -> 1 \n"
36" 1 -> 2 \n"
37" 1 -> 3 \n"
38"}";
39
40int main() {
41 int num_exec = 0;
42 int x, y;
43
44 setenv(name: "KMP_TDG_DOT",value: "TRUE",replace: 1);
45 remove(filename: "tdg_0.dot");
46
47 #pragma omp parallel
48 #pragma omp single
49 {
50 int gtid = __kmpc_global_thread_num(nullptr);
51 int res = __kmpc_start_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */ 0);
52 if (res) {
53 #pragma omp task depend(out : x)
54 func(num_exec: &num_exec);
55 #pragma omp task depend(in : x) depend(out : y)
56 func(num_exec: &num_exec);
57 #pragma omp task depend(in : y)
58 func(num_exec: &num_exec);
59 #pragma omp task depend(in : y)
60 func(num_exec: &num_exec);
61 }
62
63 __kmpc_end_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */ 0);
64 }
65
66 assert(num_exec == 4);
67
68 std::ifstream tdg_file("tdg_0.dot");
69 assert(tdg_file.is_open());
70
71 std::stringstream tdg_file_stream;
72 tdg_file_stream << tdg_file.rdbuf();
73 int equal = tdg_string.compare(str: tdg_file_stream.str());
74
75 assert(equal == 0);
76
77 std::cout << "Passed" << std::endl;
78 return 0;
79}
80// CHECK: Passed
81

source code of openmp/runtime/test/tasking/omp_record_replay_print_dot.cpp