// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "zencompute/computeservice.h" #if ZEN_WITH_COMPUTE_SERVICES # include # include # include # include # include # include namespace zen::compute { /// Deletes directories on a background thread to avoid blocking callers. /// Useful when DeleteDirectories may stall (e.g. Wine's deferred-unlink semantics). /// /// Enqueued directories wait for a deferral period before deletion, giving /// file handles time to close. Call MarkReady() with the ActionLsn to shorten /// the wait to a brief grace period (e.g. once a client has collected results). /// On shutdown, all pending directories are deleted immediately. class DeferredDirectoryDeleter { DeferredDirectoryDeleter(const DeferredDirectoryDeleter&) = delete; DeferredDirectoryDeleter& operator=(const DeferredDirectoryDeleter&) = delete; public: DeferredDirectoryDeleter(); ~DeferredDirectoryDeleter(); /// Enqueue a directory for deferred deletion, associated with an action LSN. void Enqueue(int ActionLsn, std::filesystem::path Path); /// Signal that the action result has been consumed and the directory /// can be deleted after a short grace period instead of the full deferral. void MarkReady(int ActionLsn); /// Drain the queue and join the background thread. Idempotent. void Shutdown(); private: struct QueueEntry { int ActionLsn; std::filesystem::path Path; }; std::mutex m_Mutex; std::condition_variable m_Cv; std::deque m_Queue; std::vector m_ReadyLsns; bool m_Done = false; std::thread m_Thread; void ThreadFunction(); }; } // namespace zen::compute #endif #if ZEN_WITH_TESTS namespace zen::compute { void deferreddeleter_forcelink(); // internal } // namespace zen::compute #endif