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> 26*0fca6ea1SDimitry Andric #include <deque> 27349cc55cSDimitry Andric #include <mutex> 28349cc55cSDimitry Andric #include <thread> 29349cc55cSDimitry Andric #endif 30349cc55cSDimitry Andric 31349cc55cSDimitry Andric namespace llvm { 32349cc55cSDimitry Andric namespace orc { 33349cc55cSDimitry Andric 34349cc55cSDimitry Andric /// Represents an abstract task for ORC to run. 35349cc55cSDimitry Andric class Task : public RTTIExtends<Task, RTTIRoot> { 36349cc55cSDimitry Andric public: 37349cc55cSDimitry Andric static char ID; 38349cc55cSDimitry Andric 391fd87a68SDimitry Andric virtual ~Task() = default; 40349cc55cSDimitry Andric 41349cc55cSDimitry Andric /// Description of the task to be performed. Used for logging. 42349cc55cSDimitry Andric virtual void printDescription(raw_ostream &OS) = 0; 43349cc55cSDimitry Andric 44349cc55cSDimitry Andric /// Run the task. 45349cc55cSDimitry Andric virtual void run() = 0; 46349cc55cSDimitry Andric 47349cc55cSDimitry Andric private: 48349cc55cSDimitry Andric void anchor() override; 49349cc55cSDimitry Andric }; 50349cc55cSDimitry Andric 51349cc55cSDimitry Andric /// Base class for generic tasks. 52349cc55cSDimitry Andric class GenericNamedTask : public RTTIExtends<GenericNamedTask, Task> { 53349cc55cSDimitry Andric public: 54349cc55cSDimitry Andric static char ID; 55349cc55cSDimitry Andric static const char *DefaultDescription; 56349cc55cSDimitry Andric }; 57349cc55cSDimitry Andric 58349cc55cSDimitry Andric /// Generic task implementation. 59349cc55cSDimitry Andric template <typename FnT> class GenericNamedTaskImpl : public GenericNamedTask { 60349cc55cSDimitry Andric public: 61349cc55cSDimitry Andric GenericNamedTaskImpl(FnT &&Fn, std::string DescBuffer) 62349cc55cSDimitry Andric : Fn(std::forward<FnT>(Fn)), Desc(DescBuffer.c_str()), 63349cc55cSDimitry Andric DescBuffer(std::move(DescBuffer)) {} 64349cc55cSDimitry Andric GenericNamedTaskImpl(FnT &&Fn, const char *Desc) 65349cc55cSDimitry Andric : Fn(std::forward<FnT>(Fn)), Desc(Desc) { 66349cc55cSDimitry Andric assert(Desc && "Description cannot be null"); 67349cc55cSDimitry Andric } 68349cc55cSDimitry Andric void printDescription(raw_ostream &OS) override { OS << Desc; } 69349cc55cSDimitry Andric void run() override { Fn(); } 70349cc55cSDimitry Andric 71349cc55cSDimitry Andric private: 72349cc55cSDimitry Andric FnT Fn; 73349cc55cSDimitry Andric const char *Desc; 74349cc55cSDimitry Andric std::string DescBuffer; 75349cc55cSDimitry Andric }; 76349cc55cSDimitry Andric 77349cc55cSDimitry Andric /// Create a generic named task from a std::string description. 78349cc55cSDimitry Andric template <typename FnT> 79349cc55cSDimitry Andric std::unique_ptr<GenericNamedTask> makeGenericNamedTask(FnT &&Fn, 80349cc55cSDimitry Andric std::string Desc) { 81349cc55cSDimitry Andric return std::make_unique<GenericNamedTaskImpl<FnT>>(std::forward<FnT>(Fn), 82349cc55cSDimitry Andric std::move(Desc)); 83349cc55cSDimitry Andric } 84349cc55cSDimitry Andric 85349cc55cSDimitry Andric /// Create a generic named task from a const char * description. 86349cc55cSDimitry Andric template <typename FnT> 87349cc55cSDimitry Andric std::unique_ptr<GenericNamedTask> 88349cc55cSDimitry Andric makeGenericNamedTask(FnT &&Fn, const char *Desc = nullptr) { 89349cc55cSDimitry Andric if (!Desc) 90349cc55cSDimitry Andric Desc = GenericNamedTask::DefaultDescription; 91349cc55cSDimitry Andric return std::make_unique<GenericNamedTaskImpl<FnT>>(std::forward<FnT>(Fn), 92349cc55cSDimitry Andric Desc); 93349cc55cSDimitry Andric } 94349cc55cSDimitry Andric 95349cc55cSDimitry Andric /// Abstract base for classes that dispatch ORC Tasks. 96349cc55cSDimitry Andric class TaskDispatcher { 97349cc55cSDimitry Andric public: 98349cc55cSDimitry Andric virtual ~TaskDispatcher(); 99349cc55cSDimitry Andric 100349cc55cSDimitry Andric /// Run the given task. 101349cc55cSDimitry Andric virtual void dispatch(std::unique_ptr<Task> T) = 0; 102349cc55cSDimitry Andric 103349cc55cSDimitry Andric /// Called by ExecutionSession. Waits until all tasks have completed. 104349cc55cSDimitry Andric virtual void shutdown() = 0; 105349cc55cSDimitry Andric }; 106349cc55cSDimitry Andric 107349cc55cSDimitry Andric /// Runs all tasks on the current thread. 108349cc55cSDimitry Andric class InPlaceTaskDispatcher : public TaskDispatcher { 109349cc55cSDimitry Andric public: 110349cc55cSDimitry Andric void dispatch(std::unique_ptr<Task> T) override; 111349cc55cSDimitry Andric void shutdown() override; 112349cc55cSDimitry Andric }; 113349cc55cSDimitry Andric 114349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS 115349cc55cSDimitry Andric 116349cc55cSDimitry Andric class DynamicThreadPoolTaskDispatcher : public TaskDispatcher { 117349cc55cSDimitry Andric public: 118*0fca6ea1SDimitry Andric DynamicThreadPoolTaskDispatcher( 119*0fca6ea1SDimitry Andric std::optional<size_t> MaxMaterializationThreads) 120*0fca6ea1SDimitry Andric : MaxMaterializationThreads(MaxMaterializationThreads) {} 121349cc55cSDimitry Andric void dispatch(std::unique_ptr<Task> T) override; 122349cc55cSDimitry Andric void shutdown() override; 123349cc55cSDimitry Andric private: 124349cc55cSDimitry Andric std::mutex DispatchMutex; 125349cc55cSDimitry Andric bool Running = true; 126349cc55cSDimitry Andric size_t Outstanding = 0; 127349cc55cSDimitry Andric std::condition_variable OutstandingCV; 128*0fca6ea1SDimitry Andric 129*0fca6ea1SDimitry Andric std::optional<size_t> MaxMaterializationThreads; 130*0fca6ea1SDimitry Andric size_t NumMaterializationThreads = 0; 131*0fca6ea1SDimitry Andric std::deque<std::unique_ptr<Task>> MaterializationTaskQueue; 132349cc55cSDimitry Andric }; 133349cc55cSDimitry Andric 134349cc55cSDimitry Andric #endif // LLVM_ENABLE_THREADS 135349cc55cSDimitry Andric 136349cc55cSDimitry Andric } // End namespace orc 137349cc55cSDimitry Andric } // End namespace llvm 138349cc55cSDimitry Andric 139349cc55cSDimitry Andric #endif // LLVM_EXECUTIONENGINE_ORC_TASKDISPATCH_H 140