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