diff foosdk/sdk/foobar2000/helpers/fb2kWorkerTool.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/foobar2000/helpers/fb2kWorkerTool.h	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,69 @@
+#pragma once
+#include <functional>
+#include <list>
+
+#include <SDK/threadPool.h>
+
+namespace fb2k {
+    class workerTool {
+    public:
+        struct work_t {
+            std::function<void()> work, done;
+        };
+
+        void operator+=(work_t && work) {
+            m_workQueue.push_back( std::make_shared< work_t> ( std::move(work) ) );
+            kickWork();
+        }
+        void flush() {
+            if ( m_working ) {
+                m_abort->set();
+                m_abort = std::make_shared<abort_callback_impl>();
+                m_working = false;
+            }
+            m_workQueue.clear();
+        }
+
+        void workDone() {
+            m_working = false;
+            kickWork();
+        }
+        void kickWork() {
+            PFC_ASSERT( core_api::is_main_thread() );
+            if (!m_working && !m_workQueue.empty()) {
+                m_working = true;
+                auto iter = m_workQueue.begin();
+                auto work = std::move(*iter); m_workQueue.erase(iter);
+                auto pThis = this;
+                auto a = m_abort;
+                fb2k::inCpuWorkerThread( [ work, pThis, a] {
+                    try {
+                        // release lambdas early, synchronously from same context as they're executed
+                        { auto f = std::move(work->work); if (f) f(); }
+                        a->check();
+                        fb2k::inMainThread( [work, pThis, a] {
+                            if ( ! a->is_set() ) {
+                                // release lambdas early, synchronously from same context as they're executed
+                                { auto f = std::move(work->done); if (f) f(); }
+                                pThis->workDone();
+                            }
+                        });
+                    } catch(exception_aborted const &) {}
+                } );
+            }
+        }
+        
+        workerTool() {}
+        ~workerTool() { m_abort->set(); }
+        workerTool(const workerTool&) = delete;
+        void operator=(const workerTool&) = delete;
+        
+        std::shared_ptr<abort_callback_impl> aborter() const { return m_abort; }
+    private:
+        std::shared_ptr<abort_callback_impl> m_abort = std::make_shared<abort_callback_impl>();
+        
+        bool m_working = false;
+        std::list< std::shared_ptr<work_t> > m_workQueue;
+    };
+
+}