diff options
Diffstat (limited to 'src/envfs.h')
| -rw-r--r-- | src/envfs.h | 96 |
1 files changed, 83 insertions, 13 deletions
diff --git a/src/envfs.h b/src/envfs.h index 001f2d09..8790b071 100644 --- a/src/envfs.h +++ b/src/envfs.h @@ -33,13 +33,13 @@ class ThreadPool { public: ThreadPool(std::size_t max=1) - : m_threads(max) { + setMax(max); } ~ThreadPool() { - join(); + stopAndJoin(); } void setMax(std::size_t n) @@ -47,15 +47,40 @@ public: m_threads.resize(n); } - void join() + 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()) { @@ -67,15 +92,7 @@ public: bool expected = false; if (ti.busy.compare_exchange_strong(expected, true)) { - if (ti.thread.joinable()) { - ti.thread.join(); - } - - ti.thread = std::thread([&]{ - ti.o.run(); - ti.busy = false; - }); - + ti.wakeup(); return ti.o; } } @@ -98,6 +115,47 @@ private: std::thread thread; std::atomic<bool> busy; T o; + + std::condition_variable cv; + std::mutex mutex; + bool ready; + + std::atomic<bool> stop; + + ThreadInfo() + : busy(true), ready(false), stop(false) + { + thread = std::thread([&]{ run(); }); + } + + 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<ThreadInfo> m_threads; @@ -109,7 +167,19 @@ using DirEndF = void (void*, std::wstring_view); using FileF = void (void*, std::wstring_view, FILETIME); void setHandleCloserThreadCount(std::size_t n); -void shrinkFs(); + + +class DirectoryWalker +{ +public: + void forEachEntry( + const std::wstring& path, void* cx, + DirStartF* dirStartF, DirEndF* dirEndF, FileF* fileF); + +private: + std::vector<std::unique_ptr<unsigned char[]>> m_buffers; +}; + void forEachEntry( const std::wstring& path, void* cx, |
