/* * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. * * NVIDIA CORPORATION and its licensors retain all intellectual property * and proprietary rights in and to this software, related documentation * and any modifications thereto. Any use, reproduction, disclosure or * distribution of this software and related documentation without an express * license agreement from NVIDIA CORPORATION is strictly prohibited. */ // This file was taken from the tev image viewer and is re-released here // under the NVIDIA Source Code License with permission from the author. #pragma once #include #include #include NGP_NAMESPACE_BEGIN class ICallable { public: virtual ~ICallable() {} virtual void operator()() = 0; }; template class Callable : public ICallable { public: Callable() = default; Callable(const T& callable) : m_callable{callable} {} Callable(T&& callable) : m_callable{std::forward(callable)} {} Callable(const Callable& other) = delete; Callable& operator=(Callable&& other) { std::swap(m_callable, other.m_callable); return *this; } Callable(Callable&& other) { *this = std::move(other); } void operator()() override { m_callable(); } private: T m_callable; }; template std::unique_ptr callable(T&& callable) { return std::make_unique>(std::forward(callable)); } class SharedQueueEmptyException {}; template class SharedQueue { public: bool empty() const { std::lock_guard lock{mMutex}; return mRawQueue.empty(); } size_t size() const { std::lock_guard lock{mMutex}; return mRawQueue.size(); } void push(T&& newElem) { std::lock_guard lock{mMutex}; mRawQueue.emplace_back(std::forward(newElem)); mDataCondition.notify_one(); } void clear() { std::lock_guard lock{mMutex}; mRawQueue.clear(); } void clearAndPush(T&& newElem) { std::lock_guard lock{mMutex}; mRawQueue.clear(); mRawQueue.emplace_back(std::forward(newElem)); mDataCondition.notify_one(); } T waitAndPop() { std::unique_lock lock{mMutex}; while (mRawQueue.empty()) { mDataCondition.wait(lock); } T result = std::move(mRawQueue.front()); mRawQueue.pop_front(); return result; } T tryPop(bool back = false) { std::unique_lock lock{mMutex}; if (mRawQueue.empty()) { throw SharedQueueEmptyException{}; } if (back) { T result = std::move(mRawQueue.back()); mRawQueue.pop_back(); return result; } else { T result = std::move(mRawQueue.front()); mRawQueue.pop_front(); return result; } } private: std::deque mRawQueue; mutable std::mutex mMutex; std::condition_variable mDataCondition; }; NGP_NAMESPACE_END