// TJP COPYRIGHT HEADER #pragma once #include #include #include #include #include #include #include namespace tjp::core::threads { // DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT // DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT struct PinnedFutures { std::thread thread; Event::Mutex mutex; Event event; std::queue> events; bool running = false; bool is_on_thread() { return thread.joinable() && (std::this_thread::get_id() == thread.get_id()); } PinnedFutures(bool start_=true) { if (start_) start(); } ~PinnedFutures() { stop(); } void run() { auto lock = lock_of(mutex); while (running) { if (events.empty()) { event.wait(lock); continue; } auto fn = std::move(events.front()); events.pop(); { auto unlock = unlock_of(mutex); fn(); } } } void start() { if (running) return; running = true; thread = std::thread([this]() { run(); }); } void stop() { { auto lock = lock_of(mutex); running = false; } event.notify_all(); if (thread.joinable()) thread.join(); } template Future on_(Future &f0) { Promise p; auto swizzle = f0.then([this, p](auto &&f) { auto lock = lock_of(mutex); events.push([p, f=std::move(f)]() { auto p_ = p; auto f_ = f; p_.consume([&](auto &&f) { return f.get(); }, f_); }); event.notify_one(); }); return p.get_future().then([swizzle](auto &&f1) { return f1.get(); }); } template auto run_(F &&f) { using R = decltype(f()); Promise p; { auto lock = lock_of(mutex); events.push([&]() { p.consume(f); }); event.notify_one(); } return p.get_future().get(); } template Future on(Future &f) { return on_(f); } template auto run(F &&f) { if (is_on_thread()) return f(); return run_(std::forward(f)); } } ; } // namespace