#pragma once #include #include "Common/Thread/Channel.h" #include "Common/Thread/ThreadManager.h" template class PromiseTask : public Task { public: PromiseTask() {} ~PromiseTask() { tx_->Release(); } void run() override { T *value = fun_(); tx_->Send(value); tx_->Release(); } std::function fun_; Mailbox *tx_; }; // Represents pending or actual data. // Has ownership over the data. // Single use. // TODO: Split Mailbox (rx_ and tx_) up into separate proxy objects. template class Promise { public: static Promise *Spawn(ThreadManager *threadman, std::function fun) { // std::pair, Tx> channel = CreateChannel(); Mailbox *mailbox = new Mailbox(); PromiseTask *task = new PromiseTask(); task->fun_ = fun; task->tx_ = mailbox; threadman->EnqueueTask(task); Promise *promise = new Promise(); promise->rx_ = mailbox; mailbox->AddRef(); return promise; } /* Promise(Promise &&promise) noexcept { data_ = promise.data_; ready_ = promise.ready_; rx_ = promise.rx_; }*/ ~Promise() { if (rx_) { rx_->Release(); } delete data_; } // Returns *T if the data is ready, nullptr if it's not. T *Poll() { if (ready_) { return data_; } else { if (rx_->Poll(&data_)) { ready_ = true; return data_; } else { return nullptr; } } } T *BlockUntilReady() { if (ready_) { return data_; } else { data_ = rx_->Wait(); rx_->Release(); rx_ = nullptr; ready_ = true; return data_; } } private: Promise() {} T *data_ = nullptr; bool ready_ = false; Mailbox *rx_; };