feat update
This commit is contained in:
parent
7fbf260c43
commit
d304f6da02
@ -120,6 +120,7 @@ if(SLED_BUILD_TESTS)
|
|||||||
src/exec/just_test.cc
|
src/exec/just_test.cc
|
||||||
src/any_test.cc
|
src/any_test.cc
|
||||||
src/filesystem/path_test.cc
|
src/filesystem/path_test.cc
|
||||||
|
src/futures/future_test.cc
|
||||||
# src/profiling/profiling_test.cc
|
# src/profiling/profiling_test.cc
|
||||||
src/strings/base64_test.cc
|
src/strings/base64_test.cc
|
||||||
src/cleanup_test.cc
|
src/cleanup_test.cc
|
||||||
|
@ -12,7 +12,7 @@ struct JustOperation {
|
|||||||
TReceiver receiver;
|
TReceiver receiver;
|
||||||
T value;
|
T value;
|
||||||
|
|
||||||
void Start() { receiver.SetValue(std::move(value)); }
|
void Start() { receiver.SetValue(value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
67
include/sled/exec/detail/retry.h
Normal file
67
include/sled/exec/detail/retry.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#ifndef SLED_EXEC_DETAIL_RETRY_H
|
||||||
|
#define SLED_EXEC_DETAIL_RETRY_H
|
||||||
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
#include <system_error>
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "traits.h"
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
|
||||||
|
struct RetryState {
|
||||||
|
int retry_count;
|
||||||
|
bool need_retry;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TReceiver>
|
||||||
|
struct RetryReceiver {
|
||||||
|
TReceiver receiver;
|
||||||
|
std::shared_ptr<RetryState> state;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SetValue(T &&value)
|
||||||
|
{
|
||||||
|
receiver.SetValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetError(std::exception_ptr err)
|
||||||
|
{
|
||||||
|
if (state->retry_count < 0) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetStopped() { receiver.SetStopped(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TSender, typename TReceiver>
|
||||||
|
struct RetryOperation {
|
||||||
|
ConnectResultT<TSender, RetryReceiver<TReceiver>> op;
|
||||||
|
std::shared_ptr<int> state;
|
||||||
|
|
||||||
|
void Start() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TSender>
|
||||||
|
struct RetrySender {
|
||||||
|
using S = typename std::remove_cv<typename std::remove_reference<TSender>::type>::type;
|
||||||
|
using result_t = SenderResultT<S>;
|
||||||
|
S sender;
|
||||||
|
int retry_count;
|
||||||
|
|
||||||
|
template<typename TReceiver>
|
||||||
|
RetryOperation<TSender, TReceiver> Connect(TReceiver &&receiver)
|
||||||
|
{
|
||||||
|
auto retry_state = std::make_shared<RetryState>(new RetryState{retry_count, false});
|
||||||
|
return {sender.Connect(RetryReceiver<TReceiver>{receiver, retry_state}), retry_state};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TSender>
|
||||||
|
RetrySender<TSender>
|
||||||
|
Retry(TSender &&sender, int retry_count)
|
||||||
|
{
|
||||||
|
return {std::forward<TSender>(sender), retry_count};
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_EXEC_DETAIL_RETRY_H
|
@ -8,7 +8,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
struct SyncWaitData {
|
struct SyncWaitState {
|
||||||
sled::Mutex lock;
|
sled::Mutex lock;
|
||||||
sled::ConditionVariable cv;
|
sled::ConditionVariable cv;
|
||||||
std::exception_ptr err;
|
std::exception_ptr err;
|
||||||
@ -17,7 +17,7 @@ struct SyncWaitData {
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct SyncWaitReceiver {
|
struct SyncWaitReceiver {
|
||||||
SyncWaitData &data;
|
SyncWaitState &data;
|
||||||
sled::optional<T> &value;
|
sled::optional<T> &value;
|
||||||
|
|
||||||
void SetValue(T &&val)
|
void SetValue(T &&val)
|
||||||
@ -49,7 +49,7 @@ sled::optional<SenderResultT<TSender>>
|
|||||||
SyncWait(TSender sender)
|
SyncWait(TSender sender)
|
||||||
{
|
{
|
||||||
using T = SenderResultT<TSender>;
|
using T = SenderResultT<TSender>;
|
||||||
SyncWaitData data;
|
SyncWaitState data;
|
||||||
sled::optional<T> value;
|
sled::optional<T> value;
|
||||||
|
|
||||||
auto op = sender.Connect(SyncWaitReceiver<T>{data, value});
|
auto op = sender.Connect(SyncWaitReceiver<T>{data, value});
|
||||||
|
@ -15,7 +15,11 @@ struct ThenReceiver {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
void SetValue(T &&value)
|
void SetValue(T &&value)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
receiver.SetValue(func(std::forward<T>(value)));
|
receiver.SetValue(func(std::forward<T>(value)));
|
||||||
|
} catch (...) {
|
||||||
|
receiver.SetError(std::current_exception());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetError(std::exception_ptr err) { receiver.SetError(err); }
|
void SetError(std::exception_ptr err) { receiver.SetError(err); }
|
||||||
@ -32,8 +36,9 @@ struct ThenOperation {
|
|||||||
|
|
||||||
template<typename TSender, typename F>
|
template<typename TSender, typename F>
|
||||||
struct ThenSender {
|
struct ThenSender {
|
||||||
using result_t = typename eggs::invoke_result_t<F, SenderResultT<TSender>>;
|
using S = typename std::remove_cv<typename std::remove_reference<TSender>::type>::type;
|
||||||
TSender sender;
|
using result_t = typename eggs::invoke_result_t<F, SenderResultT<S>>;
|
||||||
|
S sender;
|
||||||
F func;
|
F func;
|
||||||
|
|
||||||
template<typename TReceiver>
|
template<typename TReceiver>
|
||||||
@ -45,7 +50,7 @@ struct ThenSender {
|
|||||||
|
|
||||||
template<typename TSender, typename F>
|
template<typename TSender, typename F>
|
||||||
ThenSender<TSender, F>
|
ThenSender<TSender, F>
|
||||||
Then(TSender sender, F &&func)
|
Then(TSender &&sender, F &&func)
|
||||||
{
|
{
|
||||||
return {std::forward<TSender>(sender), std::forward<F>(func)};
|
return {std::forward<TSender>(sender), std::forward<F>(func)};
|
||||||
}
|
}
|
||||||
|
15
include/sled/futures/base_cell.h
Normal file
15
include/sled/futures/base_cell.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef SLED_FUTURES_BASE_CELL_H
|
||||||
|
#define SLED_FUTURES_BASE_CELL_H
|
||||||
|
#include <functional>
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
namespace futures {
|
||||||
|
|
||||||
|
struct BaseCell {
|
||||||
|
void *scheduler;
|
||||||
|
};
|
||||||
|
}// namespace futures
|
||||||
|
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_FUTURES_BASE_CELL_H
|
51
include/sled/futures/future.h
Normal file
51
include/sled/futures/future.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#ifndef SLED_FUTURES_FUTHRE_H
|
||||||
|
#define SLED_FUTURES_FUTHRE_H
|
||||||
|
|
||||||
|
#include "sled/any.h"
|
||||||
|
#include "sled/exec/detail/invoke_result.h"
|
||||||
|
#include "sled/optional.h"
|
||||||
|
#include "sled/synchronization/mutex.h"
|
||||||
|
#include <exception>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Future;
|
||||||
|
template<typename T>
|
||||||
|
class Promise;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct FPState : std::enable_shared_from_this<FPState<T>> {
|
||||||
|
sled::Mutex lock;
|
||||||
|
sled::optional<T> data;
|
||||||
|
std::exception_ptr err;
|
||||||
|
bool done;
|
||||||
|
sled::any priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Future {
|
||||||
|
public:
|
||||||
|
using result_t = T;
|
||||||
|
|
||||||
|
Future(std::shared_ptr<FPState<T>> state) : state_(state) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<FPState<T>> state_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Promise {
|
||||||
|
public:
|
||||||
|
using result_t = T;
|
||||||
|
|
||||||
|
void SetValue(T &&value) {}
|
||||||
|
|
||||||
|
void SetError(std::exception_ptr err) {}
|
||||||
|
|
||||||
|
Future<T> GetFuture() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_FUTURES_FUTHRE_H
|
28
include/sled/futures/just.h
Normal file
28
include/sled/futures/just.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef SLED_FUTURES_JUST_H
|
||||||
|
#define SLED_FUTURES_JUST_H
|
||||||
|
#include <utility>
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
namespace futures {
|
||||||
|
template<typename T>
|
||||||
|
struct JustCell {
|
||||||
|
T value;
|
||||||
|
|
||||||
|
template<typename R>
|
||||||
|
void Start(R receiver)
|
||||||
|
{
|
||||||
|
receiver.SetValue(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
JustCell<T>
|
||||||
|
Just(T &&t)
|
||||||
|
{
|
||||||
|
return {std::forward<T>(t)};
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace futures
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_FUTURES_JUST_H
|
40
include/sled/futures/then.h
Normal file
40
include/sled/futures/then.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
#ifndef SLED_FUTURES_THEN_H
|
||||||
|
#define SLED_FUTURES_THEN_H
|
||||||
|
#include <exception>
|
||||||
|
#include <utility>
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
namespace futures {
|
||||||
|
|
||||||
|
template<typename S, typename F>
|
||||||
|
struct ThenCell {
|
||||||
|
S sender;
|
||||||
|
F func;
|
||||||
|
|
||||||
|
// T value;
|
||||||
|
|
||||||
|
template<typename R>
|
||||||
|
void Start(R receiver)
|
||||||
|
{
|
||||||
|
sender.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
void SetValue(U &&value)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void SetError(std::exception_ptr err) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename S, typename F>
|
||||||
|
ThenCell<S, F>
|
||||||
|
Then(S sender, F &&func)
|
||||||
|
{
|
||||||
|
return {std::forward<S>(sender), std::forward<F>(func)};
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace futures
|
||||||
|
}// namespace sled
|
||||||
|
#endif// SLED_FUTURES_THEN_H
|
@ -59,25 +59,6 @@ public:
|
|||||||
Thread(const Thread &) = delete;
|
Thread(const Thread &) = delete;
|
||||||
Thread &operator=(const Thread &) = delete;
|
Thread &operator=(const Thread &) = delete;
|
||||||
|
|
||||||
void BlockingCall(std::function<void()> functor,
|
|
||||||
const Location &location = Location::Current())
|
|
||||||
{
|
|
||||||
BlockingCallImpl(functor, location);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Functor,
|
|
||||||
typename ReturnT = typename std::result_of<Functor()>::type,
|
|
||||||
typename = typename std::enable_if<!std::is_void<ReturnT>::value,
|
|
||||||
ReturnT>::type>
|
|
||||||
ReturnT BlockingCall(Functor &&functor,
|
|
||||||
const Location &location = Location::Current())
|
|
||||||
{
|
|
||||||
ReturnT result;
|
|
||||||
BlockingCall([&] { result = std::forward<Functor>(functor)(); },
|
|
||||||
location);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::unique_ptr<Thread> CreateWithSocketServer();
|
static std::unique_ptr<Thread> CreateWithSocketServer();
|
||||||
static std::unique_ptr<Thread> Create();
|
static std::unique_ptr<Thread> Create();
|
||||||
static Thread *Current();
|
static Thread *Current();
|
||||||
@ -122,8 +103,7 @@ protected:
|
|||||||
bool operator<(const DelayedMessage &dmsg) const
|
bool operator<(const DelayedMessage &dmsg) const
|
||||||
{
|
{
|
||||||
return (dmsg.run_time_ms < run_time_ms)
|
return (dmsg.run_time_ms < run_time_ms)
|
||||||
|| ((dmsg.run_time_ms == run_time_ms)
|
|| ((dmsg.run_time_ms == run_time_ms) && (dmsg.message_number < message_number));
|
||||||
&& (dmsg.message_number < message_number));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t delay_ms;
|
int64_t delay_ms;
|
||||||
@ -132,15 +112,12 @@ protected:
|
|||||||
mutable std::function<void()> functor;
|
mutable std::function<void()> functor;
|
||||||
};
|
};
|
||||||
|
|
||||||
void PostTaskImpl(std::function<void()> &&task,
|
void PostTaskImpl(std::function<void()> &&task, const PostTaskTraits &traits, const Location &location) override;
|
||||||
const PostTaskTraits &traits,
|
|
||||||
const Location &location) override;
|
|
||||||
void PostDelayedTaskImpl(std::function<void()> &&task,
|
void PostDelayedTaskImpl(std::function<void()> &&task,
|
||||||
TimeDelta delay,
|
TimeDelta delay,
|
||||||
const PostDelayedTaskTraits &traits,
|
const PostDelayedTaskTraits &traits,
|
||||||
const Location &location) override;
|
const Location &location) override;
|
||||||
virtual void BlockingCallImpl(std::function<void()> functor,
|
void BlockingCallImpl(std::function<void()> &&functor, const Location &location) override;
|
||||||
const Location &location);
|
|
||||||
|
|
||||||
void DoInit();
|
void DoInit();
|
||||||
void DoDestroy();
|
void DoDestroy();
|
||||||
@ -150,8 +127,7 @@ private:
|
|||||||
std::function<void()> Get(int cmsWait);
|
std::function<void()> Get(int cmsWait);
|
||||||
void Dispatch(std::function<void()> &&task);
|
void Dispatch(std::function<void()> &&task);
|
||||||
static void *PreRun(void *pv);
|
static void *PreRun(void *pv);
|
||||||
bool WrapCurrentWithThreadManager(ThreadManager *thread_manager,
|
bool WrapCurrentWithThreadManager(ThreadManager *thread_manager, bool need_synchronize_access);
|
||||||
bool need_synchronize_access);
|
|
||||||
bool IsRunning();
|
bool IsRunning();
|
||||||
|
|
||||||
// for ThreadManager
|
// for ThreadManager
|
||||||
@ -171,8 +147,7 @@ private:
|
|||||||
std::unique_ptr<std::thread> thread_;
|
std::unique_ptr<std::thread> thread_;
|
||||||
bool owned_;
|
bool owned_;
|
||||||
|
|
||||||
std::unique_ptr<TaskQueueBase::CurrentTaskQueueSetter>
|
std::unique_ptr<TaskQueueBase::CurrentTaskQueueSetter> task_queue_registration_;
|
||||||
task_queue_registration_;
|
|
||||||
friend class ThreadManager;
|
friend class ThreadManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
#ifndef SLED_SYSTEM_THREAD_POOL_H
|
#ifndef SLED_SYSTEM_THREAD_POOL_H
|
||||||
#define SLED_SYSTEM_THREAD_POOL_H
|
#define SLED_SYSTEM_THREAD_POOL_H
|
||||||
#include "sled/system/fiber/scheduler.h"
|
#include "sled/system/fiber/scheduler.h"
|
||||||
|
#include "sled/system/thread.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
class ThreadPool final {
|
class ThreadPool final : public TaskQueueBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @param num_threads The number of threads to create in the thread pool. If
|
* @param num_threads The number of threads to create in the thread pool. If
|
||||||
@ -18,16 +19,25 @@ public:
|
|||||||
template<typename F, typename... Args>
|
template<typename F, typename... Args>
|
||||||
auto submit(F &&f, Args &&...args) -> std::future<decltype(f(args...))>
|
auto submit(F &&f, Args &&...args) -> std::future<decltype(f(args...))>
|
||||||
{
|
{
|
||||||
std::function<decltype(f(args...))()> func =
|
std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
||||||
std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);
|
||||||
auto task_ptr =
|
scheduler_->enqueue(marl::Task([task_ptr]() { (*task_ptr)(); }));
|
||||||
std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);
|
|
||||||
scheduler->enqueue(marl::Task([task_ptr]() { (*task_ptr)(); }));
|
|
||||||
return task_ptr->get_future();
|
return task_ptr->get_future();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Delete() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void PostTaskImpl(std::function<void()> &&task, const PostTaskTraits &traits, const Location &location) override;
|
||||||
|
|
||||||
|
void PostDelayedTaskImpl(std::function<void()> &&task,
|
||||||
|
TimeDelta delay,
|
||||||
|
const PostDelayedTaskTraits &traits,
|
||||||
|
const Location &location) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sled::Scheduler *scheduler;
|
sled::Scheduler *scheduler_;
|
||||||
|
std::unique_ptr<sled::Thread> delayed_thread_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
@ -22,30 +22,23 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Deleter {
|
struct Deleter {
|
||||||
void operator()(TaskQueueBase *task_queue) const
|
void operator()(TaskQueueBase *task_queue) const { task_queue->Delete(); }
|
||||||
{
|
|
||||||
task_queue->Delete();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void Delete() = 0;
|
virtual void Delete() = 0;
|
||||||
|
|
||||||
inline void PostTask(std::function<void()> &&task,
|
inline void PostTask(std::function<void()> &&task, const Location &location = Location::Current())
|
||||||
const Location &location = Location::Current())
|
|
||||||
{
|
{
|
||||||
PostTaskImpl(std::move(task), PostTaskTraits{}, location);
|
PostTaskImpl(std::move(task), PostTaskTraits{}, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PostDelayedTask(std::function<void()> &&task,
|
inline void
|
||||||
TimeDelta delay,
|
PostDelayedTask(std::function<void()> &&task, TimeDelta delay, const Location &location = Location::Current())
|
||||||
const Location &location = Location::Current())
|
|
||||||
{
|
{
|
||||||
PostDelayedTaskImpl(std::move(task), delay, PostDelayedTaskTraits{},
|
PostDelayedTaskImpl(std::move(task), delay, PostDelayedTaskTraits{}, location);
|
||||||
location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void PostDelayedHighPrecisionTask(std::function<void()> &&task,
|
||||||
PostDelayedHighPrecisionTask(std::function<void()> &&task,
|
|
||||||
TimeDelta delay,
|
TimeDelta delay,
|
||||||
const Location &location = Location::Current())
|
const Location &location = Location::Current())
|
||||||
{
|
{
|
||||||
@ -53,8 +46,7 @@ public:
|
|||||||
PostDelayedTaskImpl(std::move(task), delay, traits, location);
|
PostDelayedTaskImpl(std::move(task), delay, traits, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void PostDelayedTaskWithPrecision(DelayPrecision precision,
|
||||||
PostDelayedTaskWithPrecision(DelayPrecision precision,
|
|
||||||
std::function<void()> &&task,
|
std::function<void()> &&task,
|
||||||
TimeDelta delay,
|
TimeDelta delay,
|
||||||
const Location &location = Location::Current())
|
const Location &location = Location::Current())
|
||||||
@ -69,6 +61,21 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlockingCall(std::function<void()> functor, const Location &location = Location::Current())
|
||||||
|
{
|
||||||
|
BlockingCallImpl(std::move(functor), location);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Functor,
|
||||||
|
typename ReturnT = typename std::result_of<Functor()>::type,
|
||||||
|
typename = typename std::enable_if<!std::is_void<ReturnT>::value, ReturnT>::type>
|
||||||
|
ReturnT BlockingCall(Functor &&functor, const Location &location = Location::Current())
|
||||||
|
{
|
||||||
|
ReturnT result;
|
||||||
|
BlockingCall([&] { result = std::forward<Functor>(functor)(); }, location);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static TaskQueueBase *Current();
|
static TaskQueueBase *Current();
|
||||||
|
|
||||||
bool IsCurrent() const { return Current() == this; };
|
bool IsCurrent() const { return Current() == this; };
|
||||||
@ -77,20 +84,17 @@ protected:
|
|||||||
struct PostTaskTraits {};
|
struct PostTaskTraits {};
|
||||||
|
|
||||||
struct PostDelayedTaskTraits {
|
struct PostDelayedTaskTraits {
|
||||||
PostDelayedTaskTraits(bool high_precision = false)
|
PostDelayedTaskTraits(bool high_precision = false) : high_precision(high_precision) {}
|
||||||
: high_precision(high_precision)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool high_precision = false;
|
bool high_precision = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void PostTaskImpl(std::function<void()> &&task,
|
virtual void PostTaskImpl(std::function<void()> &&task, const PostTaskTraits &traits, const Location &location) = 0;
|
||||||
const PostTaskTraits &traits,
|
|
||||||
const Location &location) = 0;
|
|
||||||
virtual void PostDelayedTaskImpl(std::function<void()> &&task,
|
virtual void PostDelayedTaskImpl(std::function<void()> &&task,
|
||||||
TimeDelta delay,
|
TimeDelta delay,
|
||||||
const PostDelayedTaskTraits &traits,
|
const PostDelayedTaskTraits &traits,
|
||||||
const Location &location) = 0;
|
const Location &location) = 0;
|
||||||
|
virtual void BlockingCallImpl(std::function<void()> &&task, const Location &location);
|
||||||
virtual ~TaskQueueBase() = default;
|
virtual ~TaskQueueBase() = default;
|
||||||
|
|
||||||
class CurrentTaskQueueSetter {
|
class CurrentTaskQueueSetter {
|
||||||
@ -98,8 +102,7 @@ protected:
|
|||||||
explicit CurrentTaskQueueSetter(TaskQueueBase *task_queue);
|
explicit CurrentTaskQueueSetter(TaskQueueBase *task_queue);
|
||||||
~CurrentTaskQueueSetter();
|
~CurrentTaskQueueSetter();
|
||||||
CurrentTaskQueueSetter(const CurrentTaskQueueSetter &) = delete;
|
CurrentTaskQueueSetter(const CurrentTaskQueueSetter &) = delete;
|
||||||
CurrentTaskQueueSetter &
|
CurrentTaskQueueSetter &operator=(const CurrentTaskQueueSetter &) = delete;
|
||||||
operator=(const CurrentTaskQueueSetter &) = delete;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TaskQueueBase *const previous_;
|
TaskQueueBase *const previous_;
|
||||||
|
8
src/futures/future_test.cc
Normal file
8
src/futures/future_test.cc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <sled/futures/future.h>
|
||||||
|
|
||||||
|
TEST(Future, basic)
|
||||||
|
{
|
||||||
|
// sled::Future<int> x;
|
||||||
|
// auto res = x.Then([](int) {});
|
||||||
|
}
|
@ -45,8 +45,7 @@ void
|
|||||||
ThreadManager::RemoveInternal(Thread *message_queue)
|
ThreadManager::RemoveInternal(Thread *message_queue)
|
||||||
{
|
{
|
||||||
MutexLock lock(&cirt_);
|
MutexLock lock(&cirt_);
|
||||||
auto iter = std::find(message_queues_.begin(), message_queues_.end(),
|
auto iter = std::find(message_queues_.begin(), message_queues_.end(), message_queue);
|
||||||
message_queue);
|
|
||||||
if (iter != message_queues_.end()) { message_queues_.erase(iter); }
|
if (iter != message_queues_.end()) { message_queues_.erase(iter); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +95,7 @@ ThreadManager::ProcessAllMessageQueueInternal()
|
|||||||
MutexLock lock(&cirt_);
|
MutexLock lock(&cirt_);
|
||||||
for (Thread *queue : message_queues_) {
|
for (Thread *queue : message_queues_) {
|
||||||
queues_not_done.fetch_add(1);
|
queues_not_done.fetch_add(1);
|
||||||
auto sub =
|
auto sub = MakeCleanup([&queues_not_done] { queues_not_done.fetch_sub(1); });
|
||||||
MakeCleanup([&queues_not_done] { queues_not_done.fetch_sub(1); });
|
|
||||||
queue->PostDelayedTask([&sub] {}, TimeDelta::Zero());
|
queue->PostDelayedTask([&sub] {}, TimeDelta::Zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,9 +113,7 @@ ThreadManager::SetCurrentThreadInternal(Thread *message_queue)
|
|||||||
|
|
||||||
Thread::Thread(SocketServer *ss) : Thread(ss, /*do_init=*/true) {}
|
Thread::Thread(SocketServer *ss) : Thread(ss, /*do_init=*/true) {}
|
||||||
|
|
||||||
Thread::Thread(std::unique_ptr<SocketServer> ss)
|
Thread::Thread(std::unique_ptr<SocketServer> ss) : Thread(std::move(ss), /*do_init=*/true) {}
|
||||||
: Thread(std::move(ss), /*do_init=*/true)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Thread::Thread(SocketServer *ss, bool do_init)
|
Thread::Thread(SocketServer *ss, bool do_init)
|
||||||
: delayed_next_num_(0),
|
: delayed_next_num_(0),
|
||||||
@ -131,11 +127,7 @@ Thread::Thread(SocketServer *ss, bool do_init)
|
|||||||
if (do_init) { DoInit(); }
|
if (do_init) { DoInit(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::Thread(std::unique_ptr<SocketServer> ss, bool do_init)
|
Thread::Thread(std::unique_ptr<SocketServer> ss, bool do_init) : Thread(ss.get(), do_init) { own_ss_ = std::move(ss); }
|
||||||
: Thread(ss.get(), do_init)
|
|
||||||
{
|
|
||||||
own_ss_ = std::move(ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread::~Thread()
|
Thread::~Thread()
|
||||||
{
|
{
|
||||||
@ -244,13 +236,10 @@ Thread::Get(int cmsWait)
|
|||||||
cmsNext = cmsDelayNext;
|
cmsNext = cmsDelayNext;
|
||||||
} else {
|
} else {
|
||||||
cmsNext = std::max<int64_t>(0, cmsTotal - cmsElapsed);
|
cmsNext = std::max<int64_t>(0, cmsTotal - cmsElapsed);
|
||||||
if ((cmsDelayNext != kForever) && (cmsDelayNext < cmsNext)) {
|
if ((cmsDelayNext != kForever) && (cmsDelayNext < cmsNext)) { cmsNext = cmsDelayNext; }
|
||||||
cmsNext = cmsDelayNext;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
if (!ss_->Wait(cmsNext == kForever ? SocketServer::kForever
|
if (!ss_->Wait(cmsNext == kForever ? SocketServer::kForever : TimeDelta::Millis(cmsNext),
|
||||||
: TimeDelta::Millis(cmsNext),
|
|
||||||
/*process_io=*/true)) {
|
/*process_io=*/true)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -266,9 +255,7 @@ Thread::Get(int cmsWait)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Thread::PostTaskImpl(std::function<void()> &&task,
|
Thread::PostTaskImpl(std::function<void()> &&task, const PostTaskTraits &traits, const Location &location)
|
||||||
const PostTaskTraits &traits,
|
|
||||||
const Location &location)
|
|
||||||
{
|
{
|
||||||
if (IsQuitting()) { return; }
|
if (IsQuitting()) { return; }
|
||||||
{
|
{
|
||||||
@ -303,8 +290,7 @@ Thread::PostDelayedTaskImpl(std::function<void()> &&task,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Thread::BlockingCallImpl(std::function<void()> functor,
|
Thread::BlockingCallImpl(std::function<void()> &&functor, const Location &location)
|
||||||
const Location &location)
|
|
||||||
{
|
{
|
||||||
if (IsQuitting()) { return; }
|
if (IsQuitting()) { return; }
|
||||||
if (IsCurrent()) {
|
if (IsCurrent()) {
|
||||||
@ -373,8 +359,7 @@ Thread::SetName(const std::string &name, const void *obj)
|
|||||||
void
|
void
|
||||||
Thread::EnsureIsCurrentTaskQueue()
|
Thread::EnsureIsCurrentTaskQueue()
|
||||||
{
|
{
|
||||||
task_queue_registration_.reset(
|
task_queue_registration_.reset(new TaskQueueBase::CurrentTaskQueueSetter(this));
|
||||||
new TaskQueueBase::CurrentTaskQueueSetter(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -426,8 +411,7 @@ Thread::PreRun(void *pv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Thread::WrapCurrentWithThreadManager(ThreadManager *thread_manager,
|
Thread::WrapCurrentWithThreadManager(ThreadManager *thread_manager, bool need_synchronize_access)
|
||||||
bool need_synchronize_access)
|
|
||||||
{
|
{
|
||||||
// assert(!IsRunning());
|
// assert(!IsRunning());
|
||||||
owned_ = false;
|
owned_ = false;
|
||||||
@ -498,8 +482,7 @@ Thread::Current()
|
|||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoSocketServerThread::AutoSocketServerThread(SocketServer *ss)
|
AutoSocketServerThread::AutoSocketServerThread(SocketServer *ss) : Thread(ss, /*do_init=*/false)
|
||||||
: Thread(ss, /*do_init=*/false)
|
|
||||||
{
|
{
|
||||||
DoInit();
|
DoInit();
|
||||||
old_thread_ = ThreadManager::Instance()->CurrentThread();
|
old_thread_ = ThreadManager::Instance()->CurrentThread();
|
||||||
|
@ -1,15 +1,39 @@
|
|||||||
#include "sled/system/thread_pool.h"
|
#include "sled/system/thread_pool.h"
|
||||||
|
#include "sled/system/location.h"
|
||||||
|
#include "sled/task_queue/task_queue_base.h"
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
ThreadPool::ThreadPool(int num_threads)
|
ThreadPool::ThreadPool(int num_threads)
|
||||||
{
|
{
|
||||||
if (num_threads == -1) {
|
if (num_threads == -1) { num_threads = std::thread::hardware_concurrency(); }
|
||||||
num_threads = std::thread::hardware_concurrency();
|
scheduler_ = new sled::Scheduler(sled::Scheduler::Config().setWorkerThreadCount(num_threads));
|
||||||
}
|
|
||||||
scheduler = new sled::Scheduler(
|
|
||||||
sled::Scheduler::Config().setWorkerThreadCount(num_threads));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadPool::~ThreadPool() { delete scheduler; }
|
ThreadPool::~ThreadPool() { delete scheduler_; }
|
||||||
|
|
||||||
|
void
|
||||||
|
ThreadPool::Delete()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void
|
||||||
|
ThreadPool::PostTaskImpl(std::function<void()> &&task, const PostTaskTraits &traits, const Location &location)
|
||||||
|
{
|
||||||
|
scheduler_->enqueue(marl::Task([task] { task(); }));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ThreadPool::PostDelayedTaskImpl(std::function<void()> &&task,
|
||||||
|
TimeDelta delay,
|
||||||
|
const PostDelayedTaskTraits &traits,
|
||||||
|
const Location &location)
|
||||||
|
{
|
||||||
|
if (traits.high_precision) {
|
||||||
|
delayed_thread_->PostDelayedTaskWithPrecision(TaskQueueBase::DelayPrecision::kHigh, std::move(task), delay,
|
||||||
|
location);
|
||||||
|
} else {
|
||||||
|
delayed_thread_->PostDelayedTaskWithPrecision(TaskQueueBase::DelayPrecision::kLow, std::move(task), delay,
|
||||||
|
location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "sled/task_queue/task_queue_base.h"
|
#include "sled/task_queue/task_queue_base.h"
|
||||||
|
#include "sled/synchronization/event.h"
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
namespace {
|
namespace {
|
||||||
@ -11,12 +12,22 @@ TaskQueueBase::Current()
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(TaskQueueBase *task_queue)
|
TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(TaskQueueBase *task_queue) : previous_(current)
|
||||||
: previous_(current)
|
|
||||||
{
|
{
|
||||||
current = task_queue;
|
current = task_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() { current = previous_; }
|
TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() { current = previous_; }
|
||||||
|
|
||||||
|
void
|
||||||
|
TaskQueueBase::BlockingCallImpl(std::function<void()> &&functor, const sled::Location &from)
|
||||||
|
{
|
||||||
|
Event done;
|
||||||
|
PostTask([functor, &done] {
|
||||||
|
functor();
|
||||||
|
done.Set();
|
||||||
|
});
|
||||||
|
done.Wait(Event::kForever);
|
||||||
|
}
|
||||||
|
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
Loading…
Reference in New Issue
Block a user