xref: /aosp_15_r20/external/swiftshader/third_party/marl/examples/tasks_in_tasks.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 // Copyright 2020 The Marl Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Example of a task that creates and waits on sub tasks.
16 
17 #include "marl/defer.h"
18 #include "marl/scheduler.h"
19 #include "marl/waitgroup.h"
20 
21 #include <cstdio>
22 
main()23 int main() {
24   // Create a marl scheduler using the 4 hardware threads.
25   // Bind this scheduler to the main thread so we can call marl::schedule()
26   marl::Scheduler::Config cfg;
27   cfg.setWorkerThreadCount(4);
28 
29   marl::Scheduler scheduler(cfg);
30   scheduler.bind();
31   defer(scheduler.unbind());  // Automatically unbind before returning.
32 
33   // marl::schedule() requires the scheduler to be bound to the current thread
34   // (see above). The scheduler ensures that tasks are run on a thread with the
35   // same scheduler automatically bound, so we don't need to call
36   // marl::Scheduler::bind() again below.
37 
38   // Sequence of task events:
39   //   __________________________________________________________
40   //  |                                                          |
41   //  |               ---> [task B] ----                         |
42   //  |             /                    \                       |
43   //  |  [task A] -----> [task A: wait] -----> [task A: resume]  |
44   //  |             \                    /                       |
45   //  |               ---> [task C] ----                         |
46   //  |__________________________________________________________|
47 
48   // Create a WaitGroup for waiting for task A to finish.
49   // This has an initial count of 1 (A)
50   marl::WaitGroup a_wg(1);
51 
52   // Schedule task A
53   marl::schedule([=] {
54     defer(a_wg.done());  // Decrement a_wg when task A is done
55 
56     printf("Hello from task A\n");
57     printf("Starting tasks B and C...\n");
58 
59     // Create a WaitGroup for waiting on task B and C to finish.
60     // This has an initial count of 2 (B + C)
61     marl::WaitGroup bc_wg(2);
62 
63     // Schedule task B
64     marl::schedule([=] {
65       defer(bc_wg.done());  // Decrement bc_wg when task B is done
66       printf("Hello from task B\n");
67     });
68 
69     // Schedule task C
70     marl::schedule([=] {
71       defer(bc_wg.done());  // Decrement bc_wg when task C is done
72       printf("Hello from task C\n");
73     });
74 
75     // Wait for tasks B and C to finish.
76     bc_wg.wait();
77   });
78 
79   // Wait for task A (and so B and C) to finish.
80   a_wg.wait();
81 
82   printf("Task A has finished\n");
83 }
84