1349cc55cSDimitry Andric //===--------- TaskDispatch.h - ORC task dispatch utils ---------*- C++ -*-===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric // 9349cc55cSDimitry Andric // Task and TaskDispatch classes. 10349cc55cSDimitry Andric // 11349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 12349cc55cSDimitry Andric 13349cc55cSDimitry Andric #ifndef LLVM_EXECUTIONENGINE_ORC_TASKDISPATCH_H 14349cc55cSDimitry Andric #define LLVM_EXECUTIONENGINE_ORC_TASKDISPATCH_H 15349cc55cSDimitry Andric 16349cc55cSDimitry Andric #include "llvm/Config/llvm-config.h" 17349cc55cSDimitry Andric #include "llvm/Support/Debug.h" 18349cc55cSDimitry Andric #include "llvm/Support/ExtensibleRTTI.h" 19349cc55cSDimitry Andric #include "llvm/Support/raw_ostream.h" 20349cc55cSDimitry Andric 21349cc55cSDimitry Andric #include <cassert> 22349cc55cSDimitry Andric #include <string> 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS 25349cc55cSDimitry Andric #include <condition_variable> 26349cc55cSDimitry Andric #include <mutex> 27349cc55cSDimitry Andric #include <thread> 28349cc55cSDimitry Andric #endif 29349cc55cSDimitry Andric 30349cc55cSDimitry Andric namespace llvm { 31349cc55cSDimitry Andric namespace orc { 32349cc55cSDimitry Andric 33349cc55cSDimitry Andric /// Represents an abstract task for ORC to run. 34349cc55cSDimitry Andric class Task : public RTTIExtends<Task, RTTIRoot> { 35349cc55cSDimitry Andric public: 36349cc55cSDimitry Andric static char ID; 37349cc55cSDimitry Andric 38*1fd87a68SDimitry Andric virtual ~Task() = default; 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric /// Description of the task to be performed. Used for logging. 41349cc55cSDimitry Andric virtual void printDescription(raw_ostream &OS) = 0; 42349cc55cSDimitry Andric 43349cc55cSDimitry Andric /// Run the task. 44349cc55cSDimitry Andric virtual void run() = 0; 45349cc55cSDimitry Andric 46349cc55cSDimitry Andric private: 47349cc55cSDimitry Andric void anchor() override; 48349cc55cSDimitry Andric }; 49349cc55cSDimitry Andric 50349cc55cSDimitry Andric /// Base class for generic tasks. 51349cc55cSDimitry Andric class GenericNamedTask : public RTTIExtends<GenericNamedTask, Task> { 52349cc55cSDimitry Andric public: 53349cc55cSDimitry Andric static char ID; 54349cc55cSDimitry Andric static const char *DefaultDescription; 55349cc55cSDimitry Andric }; 56349cc55cSDimitry Andric 57349cc55cSDimitry Andric /// Generic task implementation. 58349cc55cSDimitry Andric template <typename FnT> class GenericNamedTaskImpl : public GenericNamedTask { 59349cc55cSDimitry Andric public: 60349cc55cSDimitry Andric GenericNamedTaskImpl(FnT &&Fn, std::string DescBuffer) 61349cc55cSDimitry Andric : Fn(std::forward<FnT>(Fn)), Desc(DescBuffer.c_str()), 62349cc55cSDimitry Andric DescBuffer(std::move(DescBuffer)) {} 63349cc55cSDimitry Andric GenericNamedTaskImpl(FnT &&Fn, const char *Desc) 64349cc55cSDimitry Andric : Fn(std::forward<FnT>(Fn)), Desc(Desc) { 65349cc55cSDimitry Andric assert(Desc && "Description cannot be null"); 66349cc55cSDimitry Andric } 67349cc55cSDimitry Andric void printDescription(raw_ostream &OS) override { OS << Desc; } 68349cc55cSDimitry Andric void run() override { Fn(); } 69349cc55cSDimitry Andric 70349cc55cSDimitry Andric private: 71349cc55cSDimitry Andric FnT Fn; 72349cc55cSDimitry Andric const char *Desc; 73349cc55cSDimitry Andric std::string DescBuffer; 74349cc55cSDimitry Andric }; 75349cc55cSDimitry Andric 76349cc55cSDimitry Andric /// Create a generic named task from a std::string description. 77349cc55cSDimitry Andric template <typename FnT> 78349cc55cSDimitry Andric std::unique_ptr<GenericNamedTask> makeGenericNamedTask(FnT &&Fn, 79349cc55cSDimitry Andric std::string Desc) { 80349cc55cSDimitry Andric return std::make_unique<GenericNamedTaskImpl<FnT>>(std::forward<FnT>(Fn), 81349cc55cSDimitry Andric std::move(Desc)); 82349cc55cSDimitry Andric } 83349cc55cSDimitry Andric 84349cc55cSDimitry Andric /// Create a generic named task from a const char * description. 85349cc55cSDimitry Andric template <typename FnT> 86349cc55cSDimitry Andric std::unique_ptr<GenericNamedTask> 87349cc55cSDimitry Andric makeGenericNamedTask(FnT &&Fn, const char *Desc = nullptr) { 88349cc55cSDimitry Andric if (!Desc) 89349cc55cSDimitry Andric Desc = GenericNamedTask::DefaultDescription; 90349cc55cSDimitry Andric return std::make_unique<GenericNamedTaskImpl<FnT>>(std::forward<FnT>(Fn), 91349cc55cSDimitry Andric Desc); 92349cc55cSDimitry Andric } 93349cc55cSDimitry Andric 94349cc55cSDimitry Andric /// Abstract base for classes that dispatch ORC Tasks. 95349cc55cSDimitry Andric class TaskDispatcher { 96349cc55cSDimitry Andric public: 97349cc55cSDimitry Andric virtual ~TaskDispatcher(); 98349cc55cSDimitry Andric 99349cc55cSDimitry Andric /// Run the given task. 100349cc55cSDimitry Andric virtual void dispatch(std::unique_ptr<Task> T) = 0; 101349cc55cSDimitry Andric 102349cc55cSDimitry Andric /// Called by ExecutionSession. Waits until all tasks have completed. 103349cc55cSDimitry Andric virtual void shutdown() = 0; 104349cc55cSDimitry Andric }; 105349cc55cSDimitry Andric 106349cc55cSDimitry Andric /// Runs all tasks on the current thread. 107349cc55cSDimitry Andric class InPlaceTaskDispatcher : public TaskDispatcher { 108349cc55cSDimitry Andric public: 109349cc55cSDimitry Andric void dispatch(std::unique_ptr<Task> T) override; 110349cc55cSDimitry Andric void shutdown() override; 111349cc55cSDimitry Andric }; 112349cc55cSDimitry Andric 113349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS 114349cc55cSDimitry Andric 115349cc55cSDimitry Andric class DynamicThreadPoolTaskDispatcher : public TaskDispatcher { 116349cc55cSDimitry Andric public: 117349cc55cSDimitry Andric void dispatch(std::unique_ptr<Task> T) override; 118349cc55cSDimitry Andric void shutdown() override; 119349cc55cSDimitry Andric private: 120349cc55cSDimitry Andric std::mutex DispatchMutex; 121349cc55cSDimitry Andric bool Running = true; 122349cc55cSDimitry Andric size_t Outstanding = 0; 123349cc55cSDimitry Andric std::condition_variable OutstandingCV; 124349cc55cSDimitry Andric }; 125349cc55cSDimitry Andric 126349cc55cSDimitry Andric #endif // LLVM_ENABLE_THREADS 127349cc55cSDimitry Andric 128349cc55cSDimitry Andric } // End namespace orc 129349cc55cSDimitry Andric } // End namespace llvm 130349cc55cSDimitry Andric 131349cc55cSDimitry Andric #endif // LLVM_EXECUTIONENGINE_ORC_TASKDISPATCH_H 132