sled/include/sled/exec/detail/sync_wait.h
2024-03-22 17:44:43 +08:00

69 lines
1.4 KiB
C++

#ifndef SLED_EXEC_DETAIL_SYNC_WAIT_H
#define SLED_EXEC_DETAIL_SYNC_WAIT_H
#pragma once
#include "sled/optional.h"
#include "sled/synchronization/mutex.h"
#include "traits.h"
#include <exception>
namespace sled {
struct SyncWaitState {
sled::Mutex lock;
sled::ConditionVariable cv;
std::exception_ptr err;
bool done = false;
};
template<typename T>
struct SyncWaitReceiver {
SyncWaitState &data;
sled::optional<T> &value;
void SetValue(T &&val)
{
sled::MutexLock lock(&data.lock);
value.emplace(val);
data.done = true;
data.cv.NotifyOne();
}
void SetError(std::exception_ptr err)
{
sled::MutexLock lock(&data.lock);
data.err = err;
data.done = true;
data.cv.NotifyOne();
}
void SetStopped(std::exception_ptr err)
{
sled::MutexLock lock(&data.lock);
data.done = true;
data.cv.NotifyOne();
}
};
template<typename TSender>
sled::optional<SenderResultT<TSender>>
SyncWait(TSender sender)
{
using T = SenderResultT<TSender>;
SyncWaitState data;
sled::optional<T> value;
auto op = sender.Connect(SyncWaitReceiver<T>{data, value});
op.Start();
sled::MutexLock lock(&data.lock);
data.cv.Wait(lock, [&data] { return data.done; });
if (data.err) { std::rethrow_exception(data.err); }
return value;
}
}// namespace sled
#endif// SLED_EXEC_DETAIL_SYNC_WAIT_H