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