// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Containers/LruCache.h" #include "CoreMinimal.h" #include "Data/RawBuffer.h" #include "DeviceBuffer.h" #include #include #include class Blob; class DeviceNativeTask; ////////////////////////////////////////////////////////////////////////// struct DeviceNativeTask_CompareStrong { bool operator()(const std::shared_ptr& LHS, const std::shared_ptr& RHS); }; ////////////////////////////////////////////////////////////////////////// struct DeviceNativeTask_CompareWeak { bool operator()(const std::weak_ptr& InLHS, const std::weak_ptr& InRHS); }; ////////////////////////////////////////////////////////////////////////// template class GenericTaskPriorityQueue : public std::priority_queue, Comparer> { using PriorityQueue = std::priority_queue, Comparer>; private: /// We don't want people using push using PriorityQueue::push; protected: mutable std::mutex Mutex; std::condition_variable CondVar; public: bool remove(PtrType value) { std::unique_lock lock(Mutex); auto it = std::find(this->c.begin(), this->c.end(), value); if (it != PriorityQueue::c.end()) { PriorityQueue::c.erase(it); return true; } else return false; } void add(PtrType p) { std::lock_guard lock(Mutex); PriorityQueue::push(p); CondVar.notify_one(); } void lock() { Mutex.lock(); } void unlock() { Mutex.unlock(); } void reserve(size_t size) { std::unique_lock lock(Mutex); PriorityQueue::c.reserve(size); } void resize(size_t size) { std::unique_lock lock(Mutex); PriorityQueue::c.resize(size); } size_t size() const { std::unique_lock lock(Mutex); return PriorityQueue::size(); } const std::vector& accessInnerVector_Unsafe() const { return PriorityQueue::c; } PtrType waitNext() { std::unique_lock lock(Mutex); /// Only start waiting if there's nothing there if (!PriorityQueue::size()) CondVar.wait(lock); auto next = PriorityQueue::top(); PriorityQueue::pop(); return next; } void wait() { std::unique_lock lock(Mutex); /// Only start waiting if there's nothing there if (!PriorityQueue::size()) CondVar.wait(lock); } std::vector to_vector() const { std::unique_lock lock(Mutex); PriorityQueue copy = *this; std::vector vec(copy.size()); size_t index = 0; while (!copy.empty()) { vec[index++] = copy.top(); copy.pop(); } return vec; } void addBeginAndEnd(PtrType begin, PtrType end) { std::unique_lock lock(Mutex); PriorityQueue::c.insert(PriorityQueue::c.begin(), begin); PriorityQueue::c.push_back(end); } void clear() { std::unique_lock lock(Mutex); PriorityQueue::c.clear(); } std::vector to_vector_and_clear() { std::unique_lock lock(Mutex); size_t index = 0; std::vector vec(PriorityQueue::size()); while (!PriorityQueue::empty()) { vec[index++] = PriorityQueue::top(); PriorityQueue::pop(); } return vec; } }; typedef GenericTaskPriorityQueue, DeviceNativeTask_CompareStrong> DeviceNativeTask_PriorityQueueStrong; typedef GenericTaskPriorityQueue, DeviceNativeTask_CompareWeak> DeviceNativeTask_PriorityQueue;