core/ThreadPool.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #ifndef _AVS_THREADPOOL_H | ||
| 2 | #define _AVS_THREADPOOL_H | ||
| 3 | |||
| 4 | #include <avisynth.h> | ||
| 5 | #include <future> | ||
| 6 | #include <vector> | ||
| 7 | |||
| 8 | typedef std::future<AVSValue> AVSFuture; | ||
| 9 | typedef std::promise<AVSValue> AVSPromise; | ||
| 10 | |||
| 11 | class InternalEnvironment; | ||
| 12 | |||
| 13 | class JobCompletion : public IJobCompletion | ||
| 14 | { | ||
| 15 | private: | ||
| 16 | const size_t max_jobs; | ||
| 17 | size_t nJobs; | ||
| 18 | |||
| 19 | public: | ||
| 20 | typedef std::pair<AVSPromise, AVSFuture> PromFutPair; | ||
| 21 | PromFutPair *pairs; | ||
| 22 | |||
| 23 | ✗ | JobCompletion(size_t _max_jobs) : | |
| 24 | ✗ | max_jobs(_max_jobs), | |
| 25 | ✗ | nJobs(0), | |
| 26 | ✗ | pairs(NULL) | |
| 27 | { | ||
| 28 | ✗ | pairs = new PromFutPair[max_jobs]; | |
| 29 | |||
| 30 | // Initialize for first use | ||
| 31 | ✗ | nJobs = max_jobs; | |
| 32 | ✗ | Reset(); | |
| 33 | ✗ | } | |
| 34 | |||
| 35 | ✗ | AVSPromise* Add() | |
| 36 | { | ||
| 37 | ✗ | if (nJobs == max_jobs) | |
| 38 | ✗ | throw AvisynthError("The completion object is already full."); | |
| 39 | |||
| 40 | ✗ | AVSPromise* ret = &(pairs[nJobs].first); | |
| 41 | ✗ | ++nJobs; | |
| 42 | ✗ | return ret; | |
| 43 | } | ||
| 44 | |||
| 45 | ✗ | virtual ~JobCompletion() | |
| 46 | ✗ | { | |
| 47 | ✗ | Wait(); | |
| 48 | ✗ | delete [] pairs; | |
| 49 | ✗ | } | |
| 50 | |||
| 51 | ✗ | void __stdcall Wait() | |
| 52 | { | ||
| 53 | ✗ | for (size_t i = 0; i < nJobs; ++i) | |
| 54 | ✗ | pairs[i].second.wait(); | |
| 55 | ✗ | } | |
| 56 | ✗ | size_t __stdcall Size() const | |
| 57 | { | ||
| 58 | ✗ | return nJobs; | |
| 59 | } | ||
| 60 | ✗ | size_t __stdcall Capacity() const | |
| 61 | { | ||
| 62 | ✗ | return max_jobs; | |
| 63 | } | ||
| 64 | ✗ | AVSValue __stdcall Get(size_t i) | |
| 65 | { | ||
| 66 | ✗ | return pairs[i].second.get(); | |
| 67 | } | ||
| 68 | #ifdef __clang__ | ||
| 69 | #pragma clang diagnostic push | ||
| 70 | #pragma clang diagnostic ignored "-Wpessimizing-move" | ||
| 71 | #elif defined(__GNUC__) | ||
| 72 | #pragma GCC diagnostic push | ||
| 73 | #pragma GCC diagnostic ignored "-Wpessimizing-move" | ||
| 74 | #elif defined(_MSC_VER) | ||
| 75 | // Add MSVC-specific pragma if needed | ||
| 76 | #endif | ||
| 77 | ✗ | void __stdcall Reset() | |
| 78 | { | ||
| 79 | ✗ | for (size_t i = 0; i < nJobs; ++i) | |
| 80 | { | ||
| 81 | // To be on the safe side, keep std::move to ensure efficient move semantics, | ||
| 82 | // even if copy elision is possible (despite compiler warnings). | ||
| 83 | // AVSValue does not have a move constructor or move assignment operator. | ||
| 84 | // It only has a copy constructor and copy assignment operator. This means that | ||
| 85 | // AVSValue objects will be copied rather than moved, which can be less efficient. | ||
| 86 | ✗ | pairs[i].first = std::move(AVSPromise()); | |
| 87 | ✗ | pairs[i].second = std::move(pairs[i].first.get_future()); | |
| 88 | } | ||
| 89 | ✗ | nJobs = 0; | |
| 90 | ✗ | } | |
| 91 | #ifdef __clang__ | ||
| 92 | #pragma clang diagnostic pop | ||
| 93 | #elif defined(__GNUC__) | ||
| 94 | #pragma GCC diagnostic pop | ||
| 95 | #elif defined(_MSC_VER) | ||
| 96 | // Add MSVC-specific pragma if needed | ||
| 97 | #endif | ||
| 98 | ✗ | void __stdcall Destroy() | |
| 99 | { | ||
| 100 | ✗ | delete this; | |
| 101 | ✗ | } | |
| 102 | }; | ||
| 103 | |||
| 104 | class ThreadPoolPimpl; | ||
| 105 | class ThreadPool | ||
| 106 | { | ||
| 107 | private: | ||
| 108 | ThreadPoolPimpl* const _pimpl; | ||
| 109 | |||
| 110 | static void ThreadFunc(size_t thread_id, ThreadPoolPimpl* const _pimpl, InternalEnvironment* env); | ||
| 111 | public: | ||
| 112 | ThreadPool(size_t nThreads, size_t nStartId, InternalEnvironment* env); | ||
| 113 | ~ThreadPool(); | ||
| 114 | |||
| 115 | void QueueJob(ThreadWorkerFuncPtr clb, void* params, InternalEnvironment* env, JobCompletion* tc); | ||
| 116 | size_t NumThreads() const; | ||
| 117 | |||
| 118 | std::vector<void*> Finish(); | ||
| 119 | void Join(); | ||
| 120 | }; | ||
| 121 | |||
| 122 | |||
| 123 | #endif // _AVS_THREADPOOL_H | ||
| 124 |