feat add futures
This commit is contained in:
parent
f8d2b051ee
commit
15bdc54bef
@ -36,7 +36,7 @@ BreakBeforeTernaryOperators: true
|
|||||||
BreakConstructorInitializers: BeforeColon
|
BreakConstructorInitializers: BeforeColon
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
BreakInheritanceList: BeforeColon
|
BreakInheritanceList: BeforeColon
|
||||||
ColumnLimit: 80
|
ColumnLimit: 120
|
||||||
CompactNamespaces: false
|
CompactNamespaces: false
|
||||||
ContinuationIndentWidth: 4
|
ContinuationIndentWidth: 4
|
||||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
|
@ -51,6 +51,7 @@ target_sources(
|
|||||||
src/synchronization/sequence_checker_internal.cc
|
src/synchronization/sequence_checker_internal.cc
|
||||||
src/synchronization/thread_local.cc
|
src/synchronization/thread_local.cc
|
||||||
src/system/location.cc
|
src/system/location.cc
|
||||||
|
src/system/pid.cc
|
||||||
src/system/thread.cc
|
src/system/thread.cc
|
||||||
src/system/thread_pool.cc
|
src/system/thread_pool.cc
|
||||||
src/task_queue/pending_task_safety_flag.cc
|
src/task_queue/pending_task_safety_flag.cc
|
||||||
@ -100,6 +101,7 @@ if(SLED_BUILD_TESTS)
|
|||||||
FetchContent_MakeAvailable(googletest)
|
FetchContent_MakeAvailable(googletest)
|
||||||
add_executable(sled_tests
|
add_executable(sled_tests
|
||||||
src/filesystem/path_test.cc
|
src/filesystem/path_test.cc
|
||||||
|
src/futures/future_test.cc
|
||||||
src/strings/base64_test.cc
|
src/strings/base64_test.cc
|
||||||
src/cleanup_test.cc
|
src/cleanup_test.cc
|
||||||
src/status_or_test.cc
|
src/status_or_test.cc
|
||||||
|
149
include/sled/futures/future.h
Normal file
149
include/sled/futures/future.h
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <exception>
|
||||||
|
#ifndef SLED_FUTURES_FUTURE_H
|
||||||
|
#define SLED_FUTURES_FUTURE_H
|
||||||
|
|
||||||
|
#include "sled/futures/state.h"
|
||||||
|
#include "sled/futures/try.h"
|
||||||
|
#include "sled/units/time_delta.h"
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
template<typename T>
|
||||||
|
class Promise;
|
||||||
|
template<typename T>
|
||||||
|
class Future;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template<typename T>
|
||||||
|
struct IsFuture : std::false_type {
|
||||||
|
typedef T Inner;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct IsFuture<Future<T>> : std::true_type {
|
||||||
|
typedef T Inner;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename F, typename... Args>
|
||||||
|
struct InvokeResult {
|
||||||
|
using Type = decltype(std::declval<F>()(std::declval<Args>()...));
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename F, typename... Args>
|
||||||
|
struct CallableWith {
|
||||||
|
template<typename T, typename = typename InvokeResult<F, Args...>::Type>
|
||||||
|
static constexpr bool check(std::nullptr_t)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename>
|
||||||
|
static constexpr bool check(...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr bool value = check(check<F>(nullptr));
|
||||||
|
};
|
||||||
|
|
||||||
|
template<bool is_try, typename F, typename... Args>
|
||||||
|
struct ArgResult {
|
||||||
|
using Function = F;
|
||||||
|
using Result = typename InvokeResult<F, Args...>::Type;
|
||||||
|
|
||||||
|
static constexpr bool IsTry() { return is_try; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename F>
|
||||||
|
struct CallableResult {
|
||||||
|
typedef typename std::conditional<
|
||||||
|
CallableWith<F>::value,
|
||||||
|
ArgResult<false, F>,
|
||||||
|
typename std::conditional<
|
||||||
|
CallableWith<F, T &&>::value,
|
||||||
|
ArgResult<false, F, T &&>,
|
||||||
|
typename std::conditional<CallableWith<F, T &>::value,
|
||||||
|
ArgResult<false, F, T &>,
|
||||||
|
typename std::conditional<CallableWith<F, Try<T> &&>::value,
|
||||||
|
ArgResult<true, F, Try<T> &&>,
|
||||||
|
ArgResult<true, F, Try<T> &>>::type>::type>::type>::type
|
||||||
|
Arg;
|
||||||
|
typedef IsFuture<typename Arg::Result> ReturnsFuture;
|
||||||
|
typedef Future<typename ReturnsFuture::Inner> Return;
|
||||||
|
};
|
||||||
|
}// namespace
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Future {
|
||||||
|
using TimeoutCallback = std::function<void()>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Future() = default;
|
||||||
|
|
||||||
|
explicit Future(std::shared_ptr<State<T>> state) : state_(std::move(state)) {}
|
||||||
|
|
||||||
|
Future(const Future &) = delete;
|
||||||
|
|
||||||
|
Future &operator=(const Future &) = delete;
|
||||||
|
Future(Future &&) = default;
|
||||||
|
Future &operator=(Future &&) = default;
|
||||||
|
|
||||||
|
bool Valid() const { return state_ != nullptr; }
|
||||||
|
|
||||||
|
template<typename F, typename R = CallableResult<F, T>>
|
||||||
|
auto Then(F &&func) -> typename R::Return
|
||||||
|
{
|
||||||
|
typedef typename R::Arg Arguments;
|
||||||
|
return ThenImpl<F, R>(std::forward<F>(func), Arguments());
|
||||||
|
}
|
||||||
|
|
||||||
|
// for returns Future<T>
|
||||||
|
template<typename F, typename R, typename... Args>
|
||||||
|
typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type
|
||||||
|
ThenImpl(F &&func, typename InvokeResult<F, Args...>::Type)
|
||||||
|
{
|
||||||
|
static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
|
||||||
|
typedef typename R::Return::Inner ValueType;
|
||||||
|
Promise<ValueType> promise;
|
||||||
|
|
||||||
|
auto next_future = promise.GetFuture();
|
||||||
|
{
|
||||||
|
auto weak_parent_state = std::weak_ptr<State<T>>(state_);
|
||||||
|
next_future.SetOnTimeout([weak_parent_state = weak_parent_state](TimeoutCallback &&cb) {
|
||||||
|
auto parent_state = weak_parent_state.lock();
|
||||||
|
if (!parent_state) { return; }
|
||||||
|
|
||||||
|
// set timeout
|
||||||
|
{
|
||||||
|
MutexLock lock(&parent_state->mutex_);
|
||||||
|
if (parent_state->progress_ != State<T>::kNone) { return; }
|
||||||
|
parent_state->progress_ = State<T>::kTimeout;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
next_future.SetCallback([weak_parent_state = weak_parent_state,
|
||||||
|
func = std::forward<std::decay<F>::type>(func),
|
||||||
|
promise = std::move(promise)](typename TryWrapper<T>::Type &&t) {
|
||||||
|
auto parent_state = weak_parent_state.lock();
|
||||||
|
if (parent_state) {
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(next_future);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<T> &Via() { return *this; }
|
||||||
|
|
||||||
|
Future<T> &OnTimeout(sled::TimeDelta duration, TimeoutCallback &&cb) { return *this; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetCallback(TryWrapper<T> &&t);
|
||||||
|
void SetOnTimeout(std::function<void(TimeoutCallback &&)> &&func);
|
||||||
|
|
||||||
|
std::shared_ptr<State<T>> state_;
|
||||||
|
};
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_FUTURES_FUTURE_H
|
49
include/sled/futures/promise.h
Normal file
49
include/sled/futures/promise.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef SLED_FUTURES_PROMISE_H
|
||||||
|
#define SLED_FUTURES_PROMISE_H
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
namespace {
|
||||||
|
enum class Progress {
|
||||||
|
kNone,
|
||||||
|
kTimeout,
|
||||||
|
kDone,
|
||||||
|
kRetrieved,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct State {
|
||||||
|
Progress progress_ = Progress::kNone;
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Future;
|
||||||
|
template<typename T>
|
||||||
|
class Try;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Promise {
|
||||||
|
public:
|
||||||
|
static Promise<T> MakeEmpty() noexcept;
|
||||||
|
Promise();
|
||||||
|
~Promise();
|
||||||
|
Promise(Promise const &) = delete;
|
||||||
|
Promise &operator=(Promise const &) = delete;
|
||||||
|
Promise(Promise<T> &&other) noexcept;
|
||||||
|
Promise &operator=(Promise<T> &&other) noexcept;
|
||||||
|
|
||||||
|
Future<T> GetFuture();
|
||||||
|
|
||||||
|
template<typename ValueType = T>
|
||||||
|
typename std::enable_if<!std::is_void<ValueType>::value>::type
|
||||||
|
SetValue(ValueType &&value)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_FUTURES_PROMISE_H
|
34
include/sled/futures/state.h
Normal file
34
include/sled/futures/state.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef SLED_FUTURES_STATE_H
|
||||||
|
#define SLED_FUTURES_STATE_H
|
||||||
|
#include "sled/futures/try.h"
|
||||||
|
#include "sled/synchronization/mutex.h"
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
template<typename T>
|
||||||
|
struct State {
|
||||||
|
public:
|
||||||
|
enum InnerState {
|
||||||
|
kNone,
|
||||||
|
kTimeout,
|
||||||
|
kDone,
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::is_same<T, void>::value || std::is_copy_constructible<T>() || std::is_move_constructible<T>(),
|
||||||
|
"Must be copyable or movable or void");
|
||||||
|
|
||||||
|
State() {}
|
||||||
|
|
||||||
|
sled::Mutex &GetMutex() { return mutex_; }
|
||||||
|
|
||||||
|
using ValueType = typename TryWrapper<T>::Type;
|
||||||
|
sled::Mutex mutex_;
|
||||||
|
ValueType value_ GUARDED_BY(mutex_);
|
||||||
|
InnerState progress_ GUARDED_BY(mutex_) = kNone;
|
||||||
|
std::function<void(std::function<void()>)> on_timeout_;
|
||||||
|
std::function<void(ValueType &&)> on_then_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_FUTURES_STATE_H
|
267
include/sled/futures/try.h
Normal file
267
include/sled/futures/try.h
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef SLED_FUTURES_TRY_H
|
||||||
|
#define SLED_FUTURES_TRY_H
|
||||||
|
#include <exception>
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Try {
|
||||||
|
enum class State {
|
||||||
|
kNone,
|
||||||
|
kException,
|
||||||
|
kValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline Try() = default;
|
||||||
|
|
||||||
|
Try(const T &t) : state_(State::kValue), value_(t) {}
|
||||||
|
|
||||||
|
Try(T &&t) : state_(State::kValue), value_(std::move(t)) {}
|
||||||
|
|
||||||
|
explicit Try(std::exception_ptr e) : state_(State::kException), exception_(std::move(e)) {}
|
||||||
|
|
||||||
|
Try(Try<T> &&other_try) noexcept : state_(other_try.state_)
|
||||||
|
{
|
||||||
|
if (state_ == State::Value) {
|
||||||
|
new (&value_) T(std::move(other_try.value_));
|
||||||
|
} else {
|
||||||
|
new (&exception_) std::exception_ptr(std::move(other_try.exception_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Try(const Try<T> &other_try) : state_(other_try.state_)
|
||||||
|
{
|
||||||
|
if (state_ == State::kValue) {
|
||||||
|
new (&value_) T(other_try.value_);
|
||||||
|
} else {
|
||||||
|
new (&exception_) std::exception_ptr(other_try.exception_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Try<T> &operator=(Try<T> &&other_try) noexcept
|
||||||
|
{
|
||||||
|
if (this == &other_try) { return *this; }
|
||||||
|
this->~Try();
|
||||||
|
state_ = other_try.state_;
|
||||||
|
if (state_ == State::kValue) {
|
||||||
|
new (&value_) T(std::move(other_try.value_));
|
||||||
|
} else {
|
||||||
|
new (&exception_) std::exception_ptr(std::move(other_try.exception_));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Try<T> &operator=(const Try<T> &other_try)
|
||||||
|
{
|
||||||
|
if (this == &other_try) { return *this; }
|
||||||
|
this->~Try();
|
||||||
|
state_ = other_try.state_;
|
||||||
|
if (state_ == State::kValue) {
|
||||||
|
new (&value_) T(other_try.value_);
|
||||||
|
} else {
|
||||||
|
new (&exception_) std::exception_ptr(other_try.exception_);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Try()
|
||||||
|
{
|
||||||
|
if (state_ == State::kValue) {
|
||||||
|
value_.~T();
|
||||||
|
} else if (state_ == State::kException) {
|
||||||
|
exception_.~exception_ptr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasValue() const noexcept { return state_ == State::kValue; }
|
||||||
|
|
||||||
|
bool HasException() const noexcept { return state_ == State::kException; }
|
||||||
|
|
||||||
|
const T &Value() const &
|
||||||
|
{
|
||||||
|
AssertHasValue();
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
T &Value() &
|
||||||
|
{
|
||||||
|
AssertHasValue();
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
T &&Value() &&
|
||||||
|
{
|
||||||
|
AssertHasValue();
|
||||||
|
return std::move(value_);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::exception_ptr &Exception() const &
|
||||||
|
{
|
||||||
|
AssertHasException();
|
||||||
|
return exception_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::exception_ptr &Exception() &
|
||||||
|
{
|
||||||
|
AssertHasException();
|
||||||
|
return exception_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::exception_ptr &&Exception() &&
|
||||||
|
{
|
||||||
|
AssertHasException();
|
||||||
|
return std::move(exception_);
|
||||||
|
}
|
||||||
|
|
||||||
|
const T &operator*() const & { return Value(); }
|
||||||
|
|
||||||
|
T &operator*() & { return Value(); }
|
||||||
|
|
||||||
|
T &&operator*() && { return Value(); }
|
||||||
|
|
||||||
|
explicit operator bool() const { return HasValue(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AssertHasValue() const
|
||||||
|
{
|
||||||
|
if (state_ == State::kNone) {
|
||||||
|
throw std::runtime_error("Try is empty");
|
||||||
|
} else if (state_ == State::kException) {
|
||||||
|
std::rethrow_exception(exception_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssertHasException() const
|
||||||
|
{
|
||||||
|
if (!HasException()) { throw std::runtime_error("Not exceptioin"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
State state_ = State::kNone;
|
||||||
|
|
||||||
|
union {
|
||||||
|
T value_;
|
||||||
|
std::exception_ptr exception_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class Try<void> {
|
||||||
|
enum class State { kValue, kException };
|
||||||
|
|
||||||
|
public:
|
||||||
|
Try() : state_(State::kValue) {}
|
||||||
|
|
||||||
|
Try(Try<void> &&other_try) : state_(other_try.state_)
|
||||||
|
{
|
||||||
|
if (state_ == State::kException) { new (&exception_) std::exception_ptr(std::move(other_try.exception_)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
Try(const Try<void> &other_try) : state_(other_try.state_)
|
||||||
|
{
|
||||||
|
if (state_ == State::kException) { new (&exception_) std::exception_ptr(std::move(other_try.exception_)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit Try(std::exception_ptr e) : exception_(std::move(e)) {}
|
||||||
|
|
||||||
|
~Try()
|
||||||
|
{
|
||||||
|
if (state_ == State::kException) { exception_.~exception_ptr(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
Try<void> &operator=(Try<void> &&other_try)
|
||||||
|
{
|
||||||
|
if (this == &other_try) { return *this; }
|
||||||
|
this->~Try();
|
||||||
|
state_ = other_try.state_;
|
||||||
|
if (state_ == State::kException) { new (&exception_) std::exception_ptr(std::move(other_try.exception_)); }
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Try<void> &operator=(const Try<void> &other_try)
|
||||||
|
{
|
||||||
|
if (this == &other_try) { return *this; }
|
||||||
|
this->~Try();
|
||||||
|
state_ = other_try.state_;
|
||||||
|
if (state_ == State::kException) { new (&exception_) std::exception_ptr(std::move(other_try.exception_)); }
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasValue() const noexcept { return state_ == State::kValue; }
|
||||||
|
|
||||||
|
bool HasException() const noexcept { return state_ == State::kException; }
|
||||||
|
|
||||||
|
const std::exception_ptr &Exception() const &
|
||||||
|
{
|
||||||
|
AssertHasException();
|
||||||
|
return exception_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::exception_ptr &Exception() &
|
||||||
|
{
|
||||||
|
AssertHasException();
|
||||||
|
return exception_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::exception_ptr &&Exception() &&
|
||||||
|
{
|
||||||
|
AssertHasException();
|
||||||
|
return std::move(exception_);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const { return HasValue(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AssertHasException() const
|
||||||
|
{
|
||||||
|
if (!HasException()) { throw std::runtime_error("Not exception"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssertHasValue() const
|
||||||
|
{
|
||||||
|
if (!HasValue()) { throw std::runtime_error("Try is empty"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
State state_;
|
||||||
|
std::exception_ptr exception_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct TryWrapper {
|
||||||
|
using Type = Try<T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct TryWrapper<Try<T>> {
|
||||||
|
using Type = Try<T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename F, typename... Args, typename ResultT = typename std::result_of<F(Args...)>::value>
|
||||||
|
typename std::enable_if<!std::is_same<void, ResultT>::value, typename TryWrapper<ResultT>::Type>::type
|
||||||
|
WrapWithTry(F &&f, Args &&...args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return typename TryWrapper<ResultT>::Type(std::forward<F>(f)(std::forward<Args>(args)...));
|
||||||
|
} catch (...) {
|
||||||
|
return typename TryWrapper<ResultT>::Type(std::current_exception());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F, typename... Args, typename ResultT = typename std::result_of<F(Args...)>::value>
|
||||||
|
typename std::enable_if<std::is_same<void, ResultT>::value, typename TryWrapper<ResultT>::Type>::type
|
||||||
|
WrapWithTry(F &&f, Args &&...args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
std::forward<F>(f)(std::forward<Args>(args)...);
|
||||||
|
return Try<void>();
|
||||||
|
} catch (...) {
|
||||||
|
return Try<void>(std::current_exception());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_FUTURES_TRY_H
|
@ -28,8 +28,7 @@ struct HasLockAndUnlock {
|
|||||||
template<typename>
|
template<typename>
|
||||||
static char Test(...);
|
static char Test(...);
|
||||||
|
|
||||||
static constexpr bool value =
|
static constexpr bool value = std::is_same<decltype(Test<T>(0)), int>::value;
|
||||||
std::is_same<decltype(Test<T>(0)), int>::value;
|
|
||||||
};
|
};
|
||||||
}// namespace internal
|
}// namespace internal
|
||||||
|
|
||||||
@ -72,9 +71,7 @@ private:
|
|||||||
std::recursive_mutex impl_;
|
std::recursive_mutex impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename TLock,
|
template<typename TLock, typename std::enable_if<internal::HasLockAndUnlock<TLock>::value, TLock>::type * = nullptr>
|
||||||
typename std::enable_if<internal::HasLockAndUnlock<TLock>::value,
|
|
||||||
TLock>::type * = nullptr>
|
|
||||||
class LockGuard final {
|
class LockGuard final {
|
||||||
public:
|
public:
|
||||||
LockGuard(const LockGuard &) = delete;
|
LockGuard(const LockGuard &) = delete;
|
||||||
@ -159,9 +156,7 @@ public:
|
|||||||
cv_.wait(lock.lock_, std::forward<Predicate>(pred));
|
cv_.wait(lock.lock_, std::forward<Predicate>(pred));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return cv_.wait_for(lock.lock_,
|
return cv_.wait_for(lock.lock_, std::chrono::milliseconds(timeout.ms()), std::forward<Predicate>(pred));
|
||||||
std::chrono::milliseconds(timeout.ms()),
|
|
||||||
std::forward<Predicate>(pred));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
include/sled/system/pid.h
Normal file
10
include/sled/system/pid.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef SLED_SYSTEM_PID_H
|
||||||
|
#define SLED_SYSTEM_PID_H
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
pid_t GetCachedPID();
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_SYSTEM_PID_H
|
10
src/futures/future_test.cc
Normal file
10
src/futures/future_test.cc
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <sled/futures/future.h>
|
||||||
|
#include <sled/futures/promise.h>
|
||||||
|
|
||||||
|
TEST(Future, Test1)
|
||||||
|
{
|
||||||
|
sled::Promise<int> promise;
|
||||||
|
sled::Future<int> future = promise.GetFuture();
|
||||||
|
promise.SetValue(42);
|
||||||
|
}
|
10
src/system/pid.cc
Normal file
10
src/system/pid.cc
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "sled/system/pid.h"
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
pid_t
|
||||||
|
GetCachedPID()
|
||||||
|
{
|
||||||
|
static pid_t cached_pid = getpid();
|
||||||
|
return cached_pid;
|
||||||
|
}
|
||||||
|
}// namespace sled
|
Loading…
Reference in New Issue
Block a user