xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TaskDispatch.h (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1*349cc55cSDimitry Andric //===--------- TaskDispatch.h - ORC task dispatch utils ---------*- C++ -*-===//
2*349cc55cSDimitry Andric //
3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*349cc55cSDimitry Andric //
7*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8*349cc55cSDimitry Andric //
9*349cc55cSDimitry Andric // Task and TaskDispatch classes.
10*349cc55cSDimitry Andric //
11*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
12*349cc55cSDimitry Andric 
13*349cc55cSDimitry Andric #ifndef LLVM_EXECUTIONENGINE_ORC_TASKDISPATCH_H
14*349cc55cSDimitry Andric #define LLVM_EXECUTIONENGINE_ORC_TASKDISPATCH_H
15*349cc55cSDimitry Andric 
16*349cc55cSDimitry Andric #include "llvm/Config/llvm-config.h"
17*349cc55cSDimitry Andric #include "llvm/Support/Debug.h"
18*349cc55cSDimitry Andric #include "llvm/Support/ExtensibleRTTI.h"
19*349cc55cSDimitry Andric #include "llvm/Support/raw_ostream.h"
20*349cc55cSDimitry Andric 
21*349cc55cSDimitry Andric #include <cassert>
22*349cc55cSDimitry Andric #include <string>
23*349cc55cSDimitry Andric 
24*349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS
25*349cc55cSDimitry Andric #include <condition_variable>
26*349cc55cSDimitry Andric #include <mutex>
27*349cc55cSDimitry Andric #include <thread>
28*349cc55cSDimitry Andric #endif
29*349cc55cSDimitry Andric 
30*349cc55cSDimitry Andric namespace llvm {
31*349cc55cSDimitry Andric namespace orc {
32*349cc55cSDimitry Andric 
33*349cc55cSDimitry Andric /// Represents an abstract task for ORC to run.
34*349cc55cSDimitry Andric class Task : public RTTIExtends<Task, RTTIRoot> {
35*349cc55cSDimitry Andric public:
36*349cc55cSDimitry Andric   static char ID;
37*349cc55cSDimitry Andric 
38*349cc55cSDimitry Andric   virtual ~Task() {}
39*349cc55cSDimitry Andric 
40*349cc55cSDimitry Andric   /// Description of the task to be performed. Used for logging.
41*349cc55cSDimitry Andric   virtual void printDescription(raw_ostream &OS) = 0;
42*349cc55cSDimitry Andric 
43*349cc55cSDimitry Andric   /// Run the task.
44*349cc55cSDimitry Andric   virtual void run() = 0;
45*349cc55cSDimitry Andric 
46*349cc55cSDimitry Andric private:
47*349cc55cSDimitry Andric   void anchor() override;
48*349cc55cSDimitry Andric };
49*349cc55cSDimitry Andric 
50*349cc55cSDimitry Andric /// Base class for generic tasks.
51*349cc55cSDimitry Andric class GenericNamedTask : public RTTIExtends<GenericNamedTask, Task> {
52*349cc55cSDimitry Andric public:
53*349cc55cSDimitry Andric   static char ID;
54*349cc55cSDimitry Andric   static const char *DefaultDescription;
55*349cc55cSDimitry Andric };
56*349cc55cSDimitry Andric 
57*349cc55cSDimitry Andric /// Generic task implementation.
58*349cc55cSDimitry Andric template <typename FnT> class GenericNamedTaskImpl : public GenericNamedTask {
59*349cc55cSDimitry Andric public:
60*349cc55cSDimitry Andric   GenericNamedTaskImpl(FnT &&Fn, std::string DescBuffer)
61*349cc55cSDimitry Andric       : Fn(std::forward<FnT>(Fn)), Desc(DescBuffer.c_str()),
62*349cc55cSDimitry Andric         DescBuffer(std::move(DescBuffer)) {}
63*349cc55cSDimitry Andric   GenericNamedTaskImpl(FnT &&Fn, const char *Desc)
64*349cc55cSDimitry Andric       : Fn(std::forward<FnT>(Fn)), Desc(Desc) {
65*349cc55cSDimitry Andric     assert(Desc && "Description cannot be null");
66*349cc55cSDimitry Andric   }
67*349cc55cSDimitry Andric   void printDescription(raw_ostream &OS) override { OS << Desc; }
68*349cc55cSDimitry Andric   void run() override { Fn(); }
69*349cc55cSDimitry Andric 
70*349cc55cSDimitry Andric private:
71*349cc55cSDimitry Andric   FnT Fn;
72*349cc55cSDimitry Andric   const char *Desc;
73*349cc55cSDimitry Andric   std::string DescBuffer;
74*349cc55cSDimitry Andric };
75*349cc55cSDimitry Andric 
76*349cc55cSDimitry Andric /// Create a generic named task from a std::string description.
77*349cc55cSDimitry Andric template <typename FnT>
78*349cc55cSDimitry Andric std::unique_ptr<GenericNamedTask> makeGenericNamedTask(FnT &&Fn,
79*349cc55cSDimitry Andric                                                        std::string Desc) {
80*349cc55cSDimitry Andric   return std::make_unique<GenericNamedTaskImpl<FnT>>(std::forward<FnT>(Fn),
81*349cc55cSDimitry Andric                                                      std::move(Desc));
82*349cc55cSDimitry Andric }
83*349cc55cSDimitry Andric 
84*349cc55cSDimitry Andric /// Create a generic named task from a const char * description.
85*349cc55cSDimitry Andric template <typename FnT>
86*349cc55cSDimitry Andric std::unique_ptr<GenericNamedTask>
87*349cc55cSDimitry Andric makeGenericNamedTask(FnT &&Fn, const char *Desc = nullptr) {
88*349cc55cSDimitry Andric   if (!Desc)
89*349cc55cSDimitry Andric     Desc = GenericNamedTask::DefaultDescription;
90*349cc55cSDimitry Andric   return std::make_unique<GenericNamedTaskImpl<FnT>>(std::forward<FnT>(Fn),
91*349cc55cSDimitry Andric                                                      Desc);
92*349cc55cSDimitry Andric }
93*349cc55cSDimitry Andric 
94*349cc55cSDimitry Andric /// Abstract base for classes that dispatch ORC Tasks.
95*349cc55cSDimitry Andric class TaskDispatcher {
96*349cc55cSDimitry Andric public:
97*349cc55cSDimitry Andric   virtual ~TaskDispatcher();
98*349cc55cSDimitry Andric 
99*349cc55cSDimitry Andric   /// Run the given task.
100*349cc55cSDimitry Andric   virtual void dispatch(std::unique_ptr<Task> T) = 0;
101*349cc55cSDimitry Andric 
102*349cc55cSDimitry Andric   /// Called by ExecutionSession. Waits until all tasks have completed.
103*349cc55cSDimitry Andric   virtual void shutdown() = 0;
104*349cc55cSDimitry Andric };
105*349cc55cSDimitry Andric 
106*349cc55cSDimitry Andric /// Runs all tasks on the current thread.
107*349cc55cSDimitry Andric class InPlaceTaskDispatcher : public TaskDispatcher {
108*349cc55cSDimitry Andric public:
109*349cc55cSDimitry Andric   void dispatch(std::unique_ptr<Task> T) override;
110*349cc55cSDimitry Andric   void shutdown() override;
111*349cc55cSDimitry Andric };
112*349cc55cSDimitry Andric 
113*349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS
114*349cc55cSDimitry Andric 
115*349cc55cSDimitry Andric class DynamicThreadPoolTaskDispatcher : public TaskDispatcher {
116*349cc55cSDimitry Andric public:
117*349cc55cSDimitry Andric   void dispatch(std::unique_ptr<Task> T) override;
118*349cc55cSDimitry Andric   void shutdown() override;
119*349cc55cSDimitry Andric private:
120*349cc55cSDimitry Andric   std::mutex DispatchMutex;
121*349cc55cSDimitry Andric   bool Running = true;
122*349cc55cSDimitry Andric   size_t Outstanding = 0;
123*349cc55cSDimitry Andric   std::condition_variable OutstandingCV;
124*349cc55cSDimitry Andric };
125*349cc55cSDimitry Andric 
126*349cc55cSDimitry Andric #endif // LLVM_ENABLE_THREADS
127*349cc55cSDimitry Andric 
128*349cc55cSDimitry Andric } // End namespace orc
129*349cc55cSDimitry Andric } // End namespace llvm
130*349cc55cSDimitry Andric 
131*349cc55cSDimitry Andric #endif // LLVM_EXECUTIONENGINE_ORC_TASKDISPATCH_H
132