Optimize Async Memory. Introduce CoroutineHandle.

This commit is contained in:
lganzzzo 2019-09-15 03:17:33 +03:00
parent 68bbb14ec4
commit 133b79f563
20 changed files with 178 additions and 161 deletions

View File

@ -186,35 +186,25 @@ CoroutineStarter& CoroutineStarter::next(CoroutineStarter&& starter) {
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AbstractCoroutine
// CoroutineHandle
std::shared_ptr<const Error> AbstractCoroutine::ERROR_UNKNOWN = std::make_shared<Error>("Unknown Error");
std::shared_ptr<const Error> CoroutineHandle::ERROR_UNKNOWN = std::make_shared<Error>("Unknown Error");
AbstractCoroutine::AbstractCoroutine()
: _CP(this)
CoroutineHandle::CoroutineHandle(Processor* processor, AbstractCoroutine* rootCoroutine)
: _PP(processor)
, _CP(rootCoroutine)
, _FP(&AbstractCoroutine::act)
, _ERR(nullptr)
, _PP(nullptr)
, _SCH_A(Action::TYPE_NONE)
, _ref(nullptr)
, m_parent(nullptr)
, m_propagatedError(&_ERR)
, m_parentReturnAction(Action(Action::TYPE_FINISH))
{}
Action AbstractCoroutine::iterate() {
try {
return _CP->call(_FP);
} catch (std::exception& e) {
*m_propagatedError = std::make_shared<Error>(e.what());
return Action::TYPE_ERROR;
} catch (...) {
*m_propagatedError = ERROR_UNKNOWN;
return Action::TYPE_ERROR;
}
};
CoroutineHandle::~CoroutineHandle() {
delete _CP;
}
Action AbstractCoroutine::takeAction(Action&& action) {
Action CoroutineHandle::takeAction(Action&& action) {
AbstractCoroutine* savedCP;
@ -224,15 +214,10 @@ Action AbstractCoroutine::takeAction(Action&& action) {
action.m_data.coroutine->m_parent = _CP;
action.m_data.coroutine->m_propagatedError = m_propagatedError;
_CP = action.m_data.coroutine;
_FP = action.m_data.coroutine->_FP;
_FP = &AbstractCoroutine::act;
return std::forward<oatpp::async::Action>(action);
case Action::TYPE_FINISH:
if(_CP == this) {
_CP = nullptr;
return std::forward<oatpp::async::Action>(action);
}
savedCP = _CP;
_CP = _CP->m_parent;
@ -252,14 +237,9 @@ Action AbstractCoroutine::takeAction(Action&& action) {
do {
action = _CP->handleError(*m_propagatedError);
if(action.m_type == Action::TYPE_ERROR) {
if(_CP == this) {
_CP = nullptr;
return std::forward<oatpp::async::Action>(action);
} else {
savedCP = _CP;
_CP = _CP->m_parent;
delete savedCP;
}
savedCP = _CP;
_CP = _CP->m_parent;
delete savedCP;
} else {
action = takeAction(std::forward<oatpp::async::Action>(action));
}
@ -274,15 +254,36 @@ Action AbstractCoroutine::takeAction(Action&& action) {
}
Action CoroutineHandle::iterate() {
try {
return _CP->call(_FP);
} catch (std::exception& e) {
*m_propagatedError = std::make_shared<Error>(e.what());
return Action::TYPE_ERROR;
} catch (...) {
*m_propagatedError = ERROR_UNKNOWN;
return Action::TYPE_ERROR;
}
}
bool CoroutineHandle::finished() const {
return _CP == nullptr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AbstractCoroutine
AbstractCoroutine::AbstractCoroutine()
: m_parent(nullptr)
, m_propagatedError(nullptr)
, m_parentReturnAction(Action(Action::TYPE_NONE))
{}
Action AbstractCoroutine::handleError(const std::shared_ptr<const Error>& error) {
(void)error;
return Action::TYPE_ERROR;
}
bool AbstractCoroutine::finished() const {
return _CP == nullptr;
}
/**
* Get parent coroutine
* @return - pointer to a parent coroutine

View File

@ -40,6 +40,7 @@
namespace oatpp { namespace async {
class CoroutineHandle; // FWD
class AbstractCoroutine; // FWD
class Processor; // FWD
class CoroutineStarter; // FWD
@ -54,6 +55,7 @@ namespace worker {
*/
class Action {
friend Processor;
friend CoroutineHandle;
friend AbstractCoroutine;
friend CoroutineStarter;
friend worker::Worker;
@ -369,15 +371,49 @@ public:
};
/**
* This class manages coroutines processing state and a chain of coroutine calls.
*/
class CoroutineHandle : public oatpp::base::Countable {
friend oatpp::collection::FastQueue<CoroutineHandle>;
friend Processor;
friend worker::Worker;
friend CoroutineWaitList;
public:
typedef oatpp::async::Action Action;
typedef oatpp::async::Error Error;
typedef Action (AbstractCoroutine::*FunctionPtr)();
private:
static std::shared_ptr<const Error> ERROR_UNKNOWN;
private:
Processor* _PP;
AbstractCoroutine* _CP;
FunctionPtr _FP;
std::shared_ptr<const Error> _ERR;
oatpp::async::Action _SCH_A;
CoroutineHandle* _ref;
private:
std::shared_ptr<const Error>* m_propagatedError;
private:
Action takeAction(Action&& action);
public:
CoroutineHandle(Processor* processor, AbstractCoroutine* rootCoroutine);
~CoroutineHandle();
Action iterate();
bool finished() const;
};
/**
* Abstract Coroutine. Base class for Coroutines. It provides state management, coroutines stack management and error reporting functionality.
*/
class AbstractCoroutine : public oatpp::base::Countable {
friend oatpp::collection::FastQueue<AbstractCoroutine>;
friend Processor;
friend CoroutineStarter;
friend worker::Worker;
friend CoroutineWaitList;
friend CoroutineHandle;
public:
/**
* Convenience typedef for Action
@ -418,22 +454,11 @@ public:
return std::unique_ptr<AbstractMemberCaller<Args...>>(new MemberCaller<T, Args...>(func));
}
private:
static std::shared_ptr<const Error> ERROR_UNKNOWN;
private:
AbstractCoroutine* _CP;
FunctionPtr _FP;
std::shared_ptr<const Error> _ERR;
Processor* _PP;
oatpp::async::Action _SCH_A;
AbstractCoroutine* _ref;
private:
AbstractCoroutine* m_parent;
std::shared_ptr<const Error>* m_propagatedError;
protected:
oatpp::async::Action m_parentReturnAction;
private:
Action takeAction(Action&& action);
public:
/**
@ -441,12 +466,6 @@ public:
*/
AbstractCoroutine();
/**
* Make one Coroutine iteration.
* @return - control Action.
*/
Action iterate();
/**
* Virtual Destructor
*/
@ -477,12 +496,6 @@ public:
*/
virtual Action handleError(const std::shared_ptr<const Error>& error);
/**
* Check if coroutine is finished
* @return - true if finished
*/
bool finished() const;
/**
* Get parent coroutine
* @return - pointer to a parent coroutine

View File

@ -42,7 +42,7 @@ void CoroutineWaitList::setListener(Listener* listener) {
m_listener = listener;
}
void CoroutineWaitList::pushFront(AbstractCoroutine* coroutine) {
void CoroutineWaitList::pushFront(CoroutineHandle* coroutine) {
{
std::lock_guard<oatpp::concurrency::SpinLock> lock(m_lock);
m_list.pushFront(coroutine);
@ -52,7 +52,7 @@ void CoroutineWaitList::pushFront(AbstractCoroutine* coroutine) {
}
}
void CoroutineWaitList::pushBack(AbstractCoroutine* coroutine) {
void CoroutineWaitList::pushBack(CoroutineHandle* coroutine) {
{
std::lock_guard<oatpp::concurrency::SpinLock> lock(m_lock);
m_list.pushBack(coroutine);

View File

@ -56,7 +56,7 @@ public:
virtual void onNewItem(CoroutineWaitList& list) = 0;
};
private:
oatpp::collection::FastQueue<AbstractCoroutine> m_list;
oatpp::collection::FastQueue<CoroutineHandle> m_list;
oatpp::concurrency::SpinLock m_lock;
Listener* m_listener = nullptr;
protected:
@ -65,14 +65,14 @@ protected:
* This method should be called by Coroutine Processor only.
* @param coroutine
*/
void pushFront(AbstractCoroutine* coroutine);
void pushFront(CoroutineHandle* coroutine);
/*
* Put coroutine on wait-list.
* This method should be called by Coroutine Processor only.
* @param coroutine
*/
void pushBack(AbstractCoroutine* coroutine);
void pushBack(CoroutineHandle* coroutine);
public:
/**

View File

@ -52,12 +52,12 @@ void Executor::SubmissionProcessor::run() {
}
void Executor::SubmissionProcessor::pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) {
void Executor::SubmissionProcessor::pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) {
(void)tasks;
std::runtime_error("[oatpp::async::Executor::SubmissionProcessor::pushTasks]: Error. This method does nothing.");
}
void Executor::SubmissionProcessor::pushOneTask(AbstractCoroutine* task) {
void Executor::SubmissionProcessor::pushOneTask(CoroutineHandle* task) {
(void)task;
std::runtime_error("[oatpp::async::Executor::SubmissionProcessor::pushOneTask]: Error. This method does nothing.");
}

View File

@ -65,9 +65,9 @@ private:
oatpp::async::Processor& getProcessor();
void pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) override;
void pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) override;
void pushOneTask(AbstractCoroutine* task) override;
void pushOneTask(CoroutineHandle* task) override;
void run();

View File

@ -34,12 +34,12 @@ void Processor::addWorker(const std::shared_ptr<worker::Worker>& worker) {
case worker::Worker::Type::IO:
m_ioWorkers.push_back(worker);
m_ioPopQueues.push_back(collection::FastQueue<AbstractCoroutine>());
m_ioPopQueues.push_back(collection::FastQueue<CoroutineHandle>());
break;
case worker::Worker::Type::TIMER:
m_timerWorkers.push_back(worker);
m_timerPopQueues.push_back(collection::FastQueue<AbstractCoroutine>());
m_timerPopQueues.push_back(collection::FastQueue<CoroutineHandle>());
break;
default:
@ -49,7 +49,7 @@ void Processor::addWorker(const std::shared_ptr<worker::Worker>& worker) {
}
void Processor::popIOTask(AbstractCoroutine* coroutine) {
void Processor::popIOTask(CoroutineHandle* coroutine) {
if(m_ioPopQueues.size() > 0) {
auto &queue = m_ioPopQueues[(++m_ioBalancer) % m_ioPopQueues.size()];
queue.pushBack(coroutine);
@ -59,7 +59,7 @@ void Processor::popIOTask(AbstractCoroutine* coroutine) {
}
}
void Processor::popTimerTask(AbstractCoroutine* coroutine) {
void Processor::popTimerTask(CoroutineHandle* coroutine) {
if(m_timerPopQueues.size() > 0) {
auto &queue = m_timerPopQueues[(++m_timerBalancer) % m_timerPopQueues.size()];
queue.pushBack(coroutine);
@ -69,7 +69,7 @@ void Processor::popTimerTask(AbstractCoroutine* coroutine) {
}
}
void Processor::addCoroutine(AbstractCoroutine* coroutine) {
void Processor::addCoroutine(CoroutineHandle* coroutine) {
if(coroutine->_PP == this) {
@ -105,12 +105,12 @@ void Processor::addCoroutine(AbstractCoroutine* coroutine) {
action.m_type = Action::TYPE_NONE;
} else {
throw std::runtime_error("[oatpp::async::processor::addCoroutine()]: Error. Attempt to schedule coroutine to wrong processor.");
throw std::runtime_error("[oatpp::async::processor::addTask()]: Error. Attempt to schedule coroutine to wrong processor.");
}
}
void Processor::pushOneTask(AbstractCoroutine* coroutine) {
void Processor::pushOneTask(CoroutineHandle* coroutine) {
{
std::lock_guard<oatpp::concurrency::SpinLock> lock(m_taskLock);
m_pushList.pushBack(coroutine);
@ -118,10 +118,10 @@ void Processor::pushOneTask(AbstractCoroutine* coroutine) {
m_taskCondition.notify_one();
}
void Processor::pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) {
void Processor::pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) {
{
std::lock_guard<oatpp::concurrency::SpinLock> lock(m_taskLock);
collection::FastQueue<AbstractCoroutine>::moveAll(tasks, m_pushList);
collection::FastQueue<CoroutineHandle>::moveAll(tasks, m_pushList);
}
m_taskCondition.notify_one();
}
@ -154,8 +154,7 @@ void Processor::popTasks() {
void Processor::consumeAllTasks() {
for(auto& submission : m_taskList) {
auto coroutine = submission->createCoroutine();
coroutine->_PP = this;
m_queue.pushBack(coroutine);
m_queue.pushBack(new CoroutineHandle(this, coroutine));
}
m_taskList.clear();
}

View File

@ -89,8 +89,8 @@ private:
std::vector<std::shared_ptr<worker::Worker>> m_ioWorkers;
std::vector<std::shared_ptr<worker::Worker>> m_timerWorkers;
std::vector<oatpp::collection::FastQueue<AbstractCoroutine>> m_ioPopQueues;
std::vector<oatpp::collection::FastQueue<AbstractCoroutine>> m_timerPopQueues;
std::vector<oatpp::collection::FastQueue<CoroutineHandle>> m_ioPopQueues;
std::vector<oatpp::collection::FastQueue<CoroutineHandle>> m_timerPopQueues;
v_word32 m_ioBalancer = 0;
v_word32 m_timerBalancer = 0;
@ -100,11 +100,11 @@ private:
oatpp::concurrency::SpinLock m_taskLock;
std::condition_variable_any m_taskCondition;
std::list<std::shared_ptr<TaskSubmission>> m_taskList;
oatpp::collection::FastQueue<AbstractCoroutine> m_pushList;
oatpp::collection::FastQueue<CoroutineHandle> m_pushList;
private:
oatpp::collection::FastQueue<AbstractCoroutine> m_queue;
oatpp::collection::FastQueue<CoroutineHandle> m_queue;
private:
@ -113,11 +113,11 @@ private:
private:
void popIOTask(AbstractCoroutine* coroutine);
void popTimerTask(AbstractCoroutine* coroutine);
void popIOTask(CoroutineHandle* coroutine);
void popTimerTask(CoroutineHandle* coroutine);
void consumeAllTasks();
void addCoroutine(AbstractCoroutine* coroutine);
void addCoroutine(CoroutineHandle* coroutine);
void popTasks();
void pushQueues();
@ -136,15 +136,15 @@ public:
/**
* Push one Coroutine back to processor.
* @param coroutine - &id:oatpp::async::AbstractCoroutine; previously popped-out(rescheduled to coworker) from this processor.
* @param coroutine - &id:oatpp::async::CoroutineHandle; previously popped-out(rescheduled to coworker) from this processor.
*/
void pushOneTask(AbstractCoroutine* coroutine);
void pushOneTask(CoroutineHandle* coroutine);
/**
* Push list of Coroutines back to processor.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::AbstractCoroutine; previously popped-out(rescheduled to coworker) from this processor.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::CoroutineHandle; previously popped-out(rescheduled to coworker) from this processor.
*/
void pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks);
void pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks);
/**
* Execute Coroutine.

View File

@ -75,7 +75,7 @@ private:
IOEventWorkerForeman* m_foreman;
Action::IOEventType m_specialization;
bool m_running;
oatpp::collection::FastQueue<AbstractCoroutine> m_backlog;
oatpp::collection::FastQueue<CoroutineHandle> m_backlog;
oatpp::concurrency::SpinLock m_backlogLock;
private:
oatpp::data::v_io_handle m_eventQueueHandle;
@ -93,7 +93,7 @@ private:
void initEventQueue();
void triggerWakeup();
void setTriggerEvent(p_char8 eventPtr);
void setCoroutineEvent(AbstractCoroutine* coroutine, int operation, p_char8 eventPtr);
void setCoroutineEvent(CoroutineHandle* coroutine, int operation, p_char8 eventPtr);
public:
/**
@ -108,15 +108,15 @@ public:
/**
* Push list of tasks to worker.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::AbstractCoroutine;.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::CoroutineHandle;.
*/
void pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) override;
void pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) override;
/**
* Push one task to worker.
* @param task - &id:AbstractCoroutine;.
* @param task - &id:CoroutineHandle;.
*/
void pushOneTask(AbstractCoroutine* task) override;
void pushOneTask(CoroutineHandle* task) override;
/**
* Run worker.
@ -162,15 +162,15 @@ public:
/**
* Push list of tasks to worker.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::AbstractCoroutine;.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::CoroutineHandle;.
*/
void pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) override;
void pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) override;
/**
* Push one task to worker.
* @param task - &id:AbstractCoroutine;.
* @param task - &id:CoroutineHandle;.
*/
void pushOneTask(AbstractCoroutine* task) override;
void pushOneTask(CoroutineHandle* task) override;
/**
* Break run loop.

View File

@ -64,17 +64,17 @@ IOEventWorker::~IOEventWorker() {
}
void IOEventWorker::pushTasks(oatpp::collection::FastQueue<AbstractCoroutine> &tasks) {
void IOEventWorker::pushTasks(oatpp::collection::FastQueue<CoroutineHandle> &tasks) {
if (tasks.first != nullptr) {
{
std::lock_guard<oatpp::concurrency::SpinLock> guard(m_backlogLock);
oatpp::collection::FastQueue<AbstractCoroutine>::moveAll(tasks, m_backlog);
oatpp::collection::FastQueue<CoroutineHandle>::moveAll(tasks, m_backlog);
}
triggerWakeup();
}
}
void IOEventWorker::pushOneTask(AbstractCoroutine *task) {
void IOEventWorker::pushOneTask(CoroutineHandle *task) {
{
std::lock_guard<oatpp::concurrency::SpinLock> guard(m_backlogLock);
m_backlog.pushBack(task);
@ -121,14 +121,14 @@ IOEventWorkerForeman::IOEventWorkerForeman()
IOEventWorkerForeman::~IOEventWorkerForeman() {
}
void IOEventWorkerForeman::pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) {
void IOEventWorkerForeman::pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) {
oatpp::collection::FastQueue<AbstractCoroutine> readerTasks;
oatpp::collection::FastQueue<AbstractCoroutine> writerTasks;
oatpp::collection::FastQueue<CoroutineHandle> readerTasks;
oatpp::collection::FastQueue<CoroutineHandle> writerTasks;
while(tasks.first != nullptr) {
AbstractCoroutine* coroutine = tasks.popFront();
CoroutineHandle* coroutine = tasks.popFront();
auto& action = getCoroutineScheduledAction(coroutine);
switch(action.getIOEventType()) {
@ -158,7 +158,7 @@ void IOEventWorkerForeman::pushTasks(oatpp::collection::FastQueue<AbstractCorout
}
void IOEventWorkerForeman::pushOneTask(AbstractCoroutine* task) {
void IOEventWorkerForeman::pushOneTask(CoroutineHandle* task) {
auto& action = getCoroutineScheduledAction(task);

View File

@ -88,7 +88,7 @@ void IOEventWorker::setTriggerEvent(p_char8 eventPtr) {
// DO NOTHING
}
void IOEventWorker::setCoroutineEvent(AbstractCoroutine* coroutine, int operation, p_char8 eventPtr) {
void IOEventWorker::setCoroutineEvent(CoroutineHandle* coroutine, int operation, p_char8 eventPtr) {
auto& action = getCoroutineScheduledAction(coroutine);
@ -157,7 +157,7 @@ void IOEventWorker::waitEvents() {
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::waitEvents()]: Error. Event loop failed.");
}
oatpp::collection::FastQueue<AbstractCoroutine> popQueue;
oatpp::collection::FastQueue<CoroutineHandle> popQueue;
for(v_int32 i = 0; i < eventsCount; i ++) {
@ -172,7 +172,7 @@ void IOEventWorker::waitEvents() {
} else {
auto coroutine = (AbstractCoroutine*) dataPtr;
auto coroutine = (CoroutineHandle*) dataPtr;
Action action = coroutine->iterate();

View File

@ -80,7 +80,7 @@ void IOEventWorker::setTriggerEvent(p_char8 eventPtr) {
}
void IOEventWorker::setCoroutineEvent(AbstractCoroutine* coroutine, int operation, p_char8 eventPtr) {
void IOEventWorker::setCoroutineEvent(CoroutineHandle* coroutine, int operation, p_char8 eventPtr) {
(void)operation;
auto& action = getCoroutineScheduledAction(coroutine);
@ -162,13 +162,13 @@ void IOEventWorker::waitEvents() {
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::waitEvents()]: Error. Event loop failed.");
}
oatpp::collection::FastQueue<AbstractCoroutine> repeatQueue;
oatpp::collection::FastQueue<AbstractCoroutine> popQueue;
oatpp::collection::FastQueue<CoroutineHandle> repeatQueue;
oatpp::collection::FastQueue<CoroutineHandle> popQueue;
for(v_int32 i = 0; i < eventsCount; i ++) {
struct kevent* event = (struct kevent *)&m_outEvents[i * sizeof(struct kevent)];
auto coroutine = (AbstractCoroutine*) event->udata;
auto coroutine = (CoroutineHandle*) event->udata;
if((event->flags & EV_ERROR) > 0) {
OATPP_LOGD("Error", "data='%s'", strerror((int)event->data));
@ -224,7 +224,7 @@ void IOEventWorker::waitEvents() {
if(repeatQueue.count > 0) {
{
std::lock_guard<oatpp::concurrency::SpinLock> lock(m_backlogLock);
oatpp::collection::FastQueue<AbstractCoroutine>::moveAll(repeatQueue, m_backlog);
oatpp::collection::FastQueue<CoroutineHandle>::moveAll(repeatQueue, m_backlog);
}
}

View File

@ -45,7 +45,7 @@ void IOEventWorker::setTriggerEvent(p_char8 eventPtr) {
throw std::runtime_error("[IOEventWorker for Windows OS is NOT IMPLEMENTED! Use IOWorker instead.]");
}
void IOEventWorker::setCoroutineEvent(AbstractCoroutine* coroutine, int operation, p_char8 eventPtr) {
void IOEventWorker::setCoroutineEvent(CoroutineHandle* coroutine, int operation, p_char8 eventPtr) {
throw std::runtime_error("[IOEventWorker for Windows OS is NOT IMPLEMENTED! Use IOWorker instead.]");
}

View File

@ -37,15 +37,15 @@ IOWorker::IOWorker()
m_thread = std::thread(&IOWorker::run, this);
}
void IOWorker::pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) {
void IOWorker::pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) {
{
std::lock_guard<oatpp::concurrency::SpinLock> guard(m_backlogLock);
oatpp::collection::FastQueue<AbstractCoroutine>::moveAll(tasks, m_backlog);
oatpp::collection::FastQueue<CoroutineHandle>::moveAll(tasks, m_backlog);
}
m_backlogCondition.notify_one();
}
void IOWorker::pushOneTask(AbstractCoroutine* task) {
void IOWorker::pushOneTask(CoroutineHandle* task) {
{
std::lock_guard<oatpp::concurrency::SpinLock> guard(m_backlogLock);
m_backlog.pushBack(task);
@ -61,12 +61,12 @@ void IOWorker::consumeBacklog(bool blockToConsume) {
while (m_backlog.first == nullptr && m_running) {
m_backlogCondition.wait(lock);
}
oatpp::collection::FastQueue<AbstractCoroutine>::moveAll(m_backlog, m_queue);
oatpp::collection::FastQueue<CoroutineHandle>::moveAll(m_backlog, m_queue);
} else {
std::unique_lock<oatpp::concurrency::SpinLock> lock(m_backlogLock, std::try_to_lock);
if (lock.owns_lock()) {
oatpp::collection::FastQueue<AbstractCoroutine>::moveAll(m_backlog, m_queue);
oatpp::collection::FastQueue<CoroutineHandle>::moveAll(m_backlog, m_queue);
}
}

View File

@ -42,8 +42,8 @@ namespace oatpp { namespace async { namespace worker {
class IOWorker : public Worker {
private:
bool m_running;
oatpp::collection::FastQueue<AbstractCoroutine> m_backlog;
oatpp::collection::FastQueue<AbstractCoroutine> m_queue;
oatpp::collection::FastQueue<CoroutineHandle> m_backlog;
oatpp::collection::FastQueue<CoroutineHandle> m_queue;
oatpp::concurrency::SpinLock m_backlogLock;
std::condition_variable_any m_backlogCondition;
private:
@ -59,15 +59,15 @@ public:
/**
* Push list of tasks to worker.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::AbstractCoroutine;.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::CoroutineHandle;.
*/
void pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) override;
void pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) override;
/**
* Push one task to worker.
* @param task - &id:AbstractCoroutine;.
* @param task - &id:CoroutineHandle;.
*/
void pushOneTask(AbstractCoroutine* task) override;
void pushOneTask(CoroutineHandle* task) override;
/**
* Run worker.

View File

@ -38,10 +38,10 @@ TimerWorker::TimerWorker(const std::chrono::duration<v_int64, std::micro>& granu
m_thread = std::thread(&TimerWorker::run, this);
}
void TimerWorker::pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) {
void TimerWorker::pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) {
{
std::lock_guard<oatpp::concurrency::SpinLock> guard(m_backlogLock);
oatpp::collection::FastQueue<AbstractCoroutine>::moveAll(tasks, m_backlog);
oatpp::collection::FastQueue<CoroutineHandle>::moveAll(tasks, m_backlog);
}
m_backlogCondition.notify_one();
}
@ -52,11 +52,11 @@ void TimerWorker::consumeBacklog() {
while (m_backlog.first == nullptr && m_queue.first == nullptr && m_running) {
m_backlogCondition.wait(lock);
}
oatpp::collection::FastQueue<AbstractCoroutine>::moveAll(m_backlog, m_queue);
oatpp::collection::FastQueue<CoroutineHandle>::moveAll(m_backlog, m_queue);
}
void TimerWorker::pushOneTask(AbstractCoroutine* task) {
void TimerWorker::pushOneTask(CoroutineHandle* task) {
{
std::lock_guard<oatpp::concurrency::SpinLock> guard(m_backlogLock);
m_backlog.pushBack(task);
@ -70,7 +70,7 @@ void TimerWorker::run() {
consumeBacklog();
auto curr = m_queue.first;
AbstractCoroutine* prev = nullptr;
CoroutineHandle* prev = nullptr;
auto startTime = std::chrono::system_clock::now();
std::chrono::microseconds ms = std::chrono::duration_cast<std::chrono::microseconds>(startTime.time_since_epoch());

View File

@ -42,8 +42,8 @@ namespace oatpp { namespace async { namespace worker {
class TimerWorker : public Worker {
private:
bool m_running;
oatpp::collection::FastQueue<AbstractCoroutine> m_backlog;
oatpp::collection::FastQueue<AbstractCoroutine> m_queue;
oatpp::collection::FastQueue<CoroutineHandle> m_backlog;
oatpp::collection::FastQueue<CoroutineHandle> m_queue;
oatpp::concurrency::SpinLock m_backlogLock;
std::condition_variable_any m_backlogCondition;
private:
@ -62,15 +62,15 @@ public:
/**
* Push list of tasks to worker.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::AbstractCoroutine;.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::CoroutineHandle;.
*/
void pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) override;
void pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) override;
/**
* Push one task to worker.
* @param task - &id:AbstractCoroutine;.
* @param task - &id:CoroutineHandle;.
*/
void pushOneTask(AbstractCoroutine* task) override;
void pushOneTask(CoroutineHandle* task) override;
/**
* Run worker.

View File

@ -30,24 +30,24 @@ Worker::Worker(Type type)
: m_type(type)
{}
void Worker::setCoroutineScheduledAction(AbstractCoroutine *CP, Action &&action) {
CP->_SCH_A = std::forward<Action>(action);
void Worker::setCoroutineScheduledAction(CoroutineHandle* coroutine, Action &&action) {
coroutine->_SCH_A = std::forward<Action>(action);
}
Action& Worker::getCoroutineScheduledAction(AbstractCoroutine* CP) {
return CP->_SCH_A;
Action& Worker::getCoroutineScheduledAction(CoroutineHandle* coroutine) {
return coroutine->_SCH_A;
}
Processor* Worker::getCoroutineProcessor(AbstractCoroutine* CP) {
return CP->_PP;
Processor* Worker::getCoroutineProcessor(CoroutineHandle* coroutine) {
return coroutine->_PP;
}
void Worker::dismissAction(Action& action) {
action.m_type = Action::TYPE_NONE;
}
AbstractCoroutine* Worker::nextCoroutine(AbstractCoroutine* CP) {
return CP->_ref;
CoroutineHandle* Worker::nextCoroutine(CoroutineHandle* coroutine) {
return coroutine->_ref;
}
Worker::Type Worker::getType() {

View File

@ -67,11 +67,11 @@ public:
private:
Type m_type;
protected:
static void setCoroutineScheduledAction(AbstractCoroutine* CP, Action&& action);
static Action& getCoroutineScheduledAction(AbstractCoroutine* CP);
static Processor* getCoroutineProcessor(AbstractCoroutine* CP);
static void setCoroutineScheduledAction(CoroutineHandle* coroutine, Action&& action);
static Action& getCoroutineScheduledAction(CoroutineHandle* coroutine);
static Processor* getCoroutineProcessor(CoroutineHandle* coroutine);
static void dismissAction(Action& action);
static AbstractCoroutine* nextCoroutine(AbstractCoroutine* CP);
static CoroutineHandle* nextCoroutine(CoroutineHandle* coroutine);
public:
/**
@ -87,15 +87,15 @@ public:
/**
* Push list of tasks to worker.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::AbstractCoroutine;.
* @param tasks - &id:oatpp::collection::FastQueue; of &id:oatpp::async::CoroutineHandle;.
*/
virtual void pushTasks(oatpp::collection::FastQueue<AbstractCoroutine>& tasks) = 0;
virtual void pushTasks(oatpp::collection::FastQueue<CoroutineHandle>& tasks) = 0;
/**
* Push one task to worker.
* @param task - &id:AbstractCoroutine;.
* @param task - &id:oatpp::async::CoroutineHandle;.
*/
virtual void pushOneTask(AbstractCoroutine* task) = 0;
virtual void pushOneTask(CoroutineHandle* task) = 0;
/**
* Break run loop.

View File

@ -49,6 +49,10 @@ void runTests() {
oatpp::base::Environment::printCompilationConfig();
OATPP_LOGI("aaa", "size_of(Coroutine)=%d", sizeof(oatpp::async::AbstractCoroutine));
OATPP_LOGI("aaa", "size_of(Action)=%d", sizeof(oatpp::async::Action));
/*
OATPP_RUN_TEST(oatpp::test::base::RegRuleTest);
OATPP_RUN_TEST(oatpp::test::base::CommandLineArgumentsTest);
@ -90,7 +94,7 @@ void runTests() {
test_port.run();
}
*/
{
oatpp::test::web::FullAsyncTest test_virtual(0, 1000);