diff --git a/src/factory/WFTask.h b/src/factory/WFTask.h index d2595f88..78c8c318 100644 --- a/src/factory/WFTask.h +++ b/src/factory/WFTask.h @@ -485,10 +485,7 @@ public: } } - void **get_mailbox() const - { - return this->mailbox; - } + void **get_mailbox() const { return this->mailbox; } public: void set_callback(std::function cb) @@ -542,6 +539,99 @@ protected: virtual ~WFMailboxTask() { } }; +class WFSelectorTask : public WFGenericTask +{ +public: + virtual int submit(void *msg) + { + void *tmp = NULL; + int ret = 0; + + if (this->message.compare_exchange_strong(tmp, msg) && msg) + { + ret = 1; + if (this->flag.exchange(true)) + { + this->state = WFT_STATE_SUCCESS; + this->subtask_done(); + } + } + + if (--this->nleft == 0) + { + if (!this->message) + { + this->state = WFT_STATE_SYS_ERROR; + this->error = ENOMSG; + this->subtask_done(); + } + + delete this; + } + + return ret; + } + + void *get_message() const { return this->message; } + +public: + void set_callback(std::function cb) + { + this->callback = std::move(cb); + } + +protected: + virtual void dispatch() + { + if (this->flag.exchange(true)) + { + this->state = WFT_STATE_SUCCESS; + this->subtask_done(); + } + + if (--this->nleft == 0) + { + if (!this->message) + { + this->state = WFT_STATE_SYS_ERROR; + this->error = ENOMSG; + this->subtask_done(); + } + + delete this; + } + } + + virtual SubTask *done() + { + SeriesWork *series = series_of(this); + + if (this->callback) + this->callback(this); + + return series->pop(); + } + +protected: + std::atomic message; + std::atomic flag; + std::atomic nleft; + std::function callback; + +public: + WFSelectorTask(size_t candidates, + std::function&& cb) : + message(NULL), + flag(false), + nleft(candidates + 1), + callback(std::move(cb)) + { + } + +protected: + virtual ~WFSelectorTask() { } +}; + class WFConditional : public WFGenericTask { public: diff --git a/src/factory/WFTaskFactory.h b/src/factory/WFTaskFactory.h index 02d30637..48573c21 100644 --- a/src/factory/WFTaskFactory.h +++ b/src/factory/WFTaskFactory.h @@ -87,9 +87,10 @@ using fsync_callback_t = std::function; using timer_callback_t = std::function; using counter_callback_t = std::function; -// Mailbox is like counter with data passing using mailbox_callback_t = std::function; +using selector_callback_t = std::function; + // Graph (DAG) task. using graph_callback_t = std::function; @@ -257,6 +258,13 @@ public: static void send_by_name(const std::string& mailbox_name, void *msg, size_t max); +public: + static WFSelectorTask *create_selector_task(size_t candidates, + selector_callback_t callback) + { + return new WFSelectorTask(candidates, std::move(callback)); + } + public: static WFConditional *create_conditional(SubTask *task, void **msgbuf) {