#ifndef ENV_ENVFS_H #define ENV_ENVFS_H #include namespace env { struct File { std::wstring name; std::wstring lcname; FILETIME lastModified; File(std::wstring_view name, FILETIME ft); }; struct Directory { std::wstring name; std::wstring lcname; std::vector dirs; std::vector files; Directory(); Directory(std::wstring_view name); }; template class ThreadPool { public: ThreadPool(std::size_t max=1) { setMax(max); } ~ThreadPool() { stopAndJoin(); } void setMax(std::size_t n) { m_threads.resize(n); } void stopAndJoin() { for (auto& ti : m_threads) { ti.stop = true; ti.wakeup(); } for (auto& ti : m_threads) { if (ti.thread.joinable()) { ti.thread.join(); } } } void waitForAll() { for (;;) { bool done = true; for (auto& ti : m_threads) { if (ti.busy) { done = false; break; } } if (done) { break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } T& request() { if (m_threads.empty()) { std::terminate(); } for (;;) { for (auto& ti : m_threads) { bool expected = false; if (ti.busy.compare_exchange_strong(expected, true)) { ti.wakeup(); return ti.o; } } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } template void forEach(F&& f) { for (auto& ti : m_threads) { f(ti.o); } } private: struct ThreadInfo { std::thread thread; std::atomic busy; T o; std::condition_variable cv; std::mutex mutex; bool ready; std::atomic stop; ThreadInfo() : busy(true), ready(false), stop(false) { thread = std::thread([&]{ run(); }); } ~ThreadInfo() { if (thread.joinable()) { stop = true; wakeup(); thread.join(); } } void wakeup() { { std::scoped_lock lock(mutex); ready = true; } cv.notify_one(); } void run() { busy = false; while (!stop) { std::unique_lock lock(mutex); cv.wait(lock, [&]{ return ready; }); if (stop) { break; } o.run(); ready = false; busy = false; } } }; std::list m_threads; }; using DirStartF = void (void*, std::wstring_view); using DirEndF = void (void*, std::wstring_view); using FileF = void (void*, std::wstring_view, FILETIME); void setHandleCloserThreadCount(std::size_t n); class DirectoryWalker { public: void forEachEntry( const std::wstring& path, void* cx, DirStartF* dirStartF, DirEndF* dirEndF, FileF* fileF); private: std::vector> m_buffers; }; void forEachEntry( const std::wstring& path, void* cx, DirStartF* dirStartF, DirEndF* dirEndF, FileF* fileF); Directory getFilesAndDirs(const std::wstring& path); Directory getFilesAndDirsWithFind(const std::wstring& path); } // namespace #endif // ENV_ENVFS_H