141 lines
2.1 KiB
C++
Executable File
141 lines
2.1 KiB
C++
Executable File
// TJP COPYRIGHT HEADER
|
|
|
|
#pragma once
|
|
|
|
#include <thread>
|
|
|
|
#include <tjp/core/threads/Lock.hpp>
|
|
#include <tjp/core/threads/UnlockGuard.hpp>
|
|
#include <tjp/core/threads/Atomic.h>
|
|
#include <tjp/core/threads/TestMutex.hpp>
|
|
#include <tjp/core/containers/Function.hpp>
|
|
|
|
#include <queue>
|
|
|
|
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<Function<void()>> 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<typename V>
|
|
Future<V> on_(Future<V> &f0)
|
|
{
|
|
Promise<V> 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<typename F>
|
|
auto run_(F &&f)
|
|
{
|
|
using R = decltype(f());
|
|
Promise<R> p;
|
|
|
|
{
|
|
auto lock = lock_of(mutex);
|
|
events.push([&]() { p.consume(f); });
|
|
event.notify_one();
|
|
}
|
|
|
|
return p.get_future().get();
|
|
}
|
|
|
|
template<typename V>
|
|
Future<V> on(Future<V> &f)
|
|
{
|
|
return on_(f);
|
|
}
|
|
|
|
template<typename F>
|
|
auto run(F &&f)
|
|
{
|
|
if (is_on_thread())
|
|
return f();
|
|
|
|
return run_(std::forward<F>(f));
|
|
}
|
|
|
|
} ;
|
|
|
|
} // namespace
|