22#ifndef MTROPOLIS_VTHREAD_H
23#define MTROPOLIS_VTHREAD_H
25#include "mtropolis/coroutine_protos.h"
26#include "mtropolis/coroutine_return_value.h"
27#include "mtropolis/debug.h"
31struct ICoroutineManager;
57 virtual VThreadState execute(
VThread *thread) = 0;
59#ifdef MTROPOLIS_DEBUG_ENABLE
61 void debugInit(
const char *name);
64 SupportStatus debugGetSupportStatus()
const override {
return kSupportStatusDone; }
65 const char *debugGetTypeName()
const override {
return "Task"; }
66 const Common::String &debugGetName()
const override {
return _debugName; }
96template<
typename TClass,
typename TData>
103 VThreadState execute(
VThread *thread)
override;
110 VThreadState (TClass::*_method)(
const TData &data);
114template<
typename TData>
123 VThreadState execute(
VThread *thread)
override;
129 VThreadState (*_func)(
const TData &data);
138 template<
typename TClass,
typename TData>
139 TData *pushTask(
const char *name, TClass *obj, VThreadState (TClass::*method)(
const TData &data));
141 template<
typename TData>
142 TData *pushTask(
const char *name, VThreadState (*func)(
const TData &data));
146 bool hasTasks()
const;
152 template<
typename TCoroutine,
typename TReturnValue,
typename ...TParams>
153 void pushCoroutineWithReturn(TReturnValue *returnValuePtr, TParams &&...args);
155 template<
typename TCoroutine,
typename TReturnValue>
156 void pushCoroutineWithReturn(TReturnValue *returnValuePtr);
158 template<
typename TCoroutine,
typename... TParams>
159 void pushCoroutine(TParams &&...args);
161 template<
typename TCoroutine>
162 void pushCoroutine();
166 void reserveFrame(
size_t frameAlignment,
size_t frameSize,
VThreadStackFrame *&outFramePtr,
size_t dataAlignment,
size_t dataSize,
void *&outDataPtr,
bool &outIsNewChunk);
167 static bool reserveFrameInChunk(
VThreadStackChunk *chunk,
size_t frameAlignment,
size_t frameSize,
VThreadStackFrame *&outFramePtr,
size_t dataAlignment,
size_t dataSize,
void *&outDataPtr);
171 template<
typename TClass,
typename TData>
172 TData *pushTaskWithFaultHandler(
const VThreadFaultIdentifier *faultID,
const char *name, TClass *obj, VThreadState (TClass::*method)(
const TData &data));
174 template<
typename TData>
175 TData *pushTaskWithFaultHandler(
const VThreadFaultIdentifier *faultID,
const char *name, VThreadState (*func)(
const TData &data));
179 uint _numActiveStackChunks;
182template<
typename TClass,
typename TData>
184 : _faultID(faultID), _target(target), _method(method) {
187template<
typename TClass,
typename TData>
188VThreadMethodData<TClass, TData>::VThreadMethodData(
const VThreadMethodData& other)
189 : _faultID(other._faultID), _target(other._target), _method(other._method), _data(other._data) {
192template<
typename TClass,
typename TData>
193VThreadMethodData<TClass, TData>::VThreadMethodData(VThreadMethodData &&other)
194 : _faultID(other._faultID), _target(other._target), _method(other._method), _data(static_cast<TData &&>(other._data)) {
197template<
typename TClass,
typename TData>
198VThreadState VThreadMethodData<TClass, TData>::execute(VThread *thread) {
199 TData data(
static_cast<TData &&
>(_data));
201 TClass *target = _target;
202 VThreadState (TClass::*method)(
const TData &) = _method;
206 return (target->*method)(data);
209template<
typename TClass,
typename TData>
210TData &VThreadMethodData<TClass, TData>::getData() {
214template<
typename TData>
215VThreadFunctionData<TData>::VThreadFunctionData(
const VThreadFaultIdentifier *faultID, VThreadState (*func)(
const TData &data))
216 : _faultID(faultID), _func(func) {
219template<
typename TData>
220VThreadFunctionData<TData>::VThreadFunctionData(
const VThreadFunctionData &other)
221 : _faultID(other._faultID), _func(other._func), _data(other._data) {
224template<
typename TData>
225VThreadFunctionData<TData>::VThreadFunctionData(VThreadFunctionData &&other)
226 : _faultID(other._faultID), _func(other._func), _data(static_cast<TData &&>(other._data)) {
229template<
typename TData>
230VThreadState VThreadFunctionData<TData>::execute(VThread *thread) {
231 TData data(
static_cast<TData &&
>(_data));
233 VThreadState (*func)(
const TData &) = _func;
240template<
typename TData>
241TData &VThreadFunctionData<TData>::getData() {
245template<
typename TCoroutine,
typename TReturnValue,
typename... TParams>
246void VThread::pushCoroutineWithReturn(TReturnValue *returnValuePtr, TParams &&...args) {
247 assert(returnValuePtr !=
nullptr);
248 this->pushCoroutineInternal(&TCoroutine::ms_compiledCoro, TCoroutine::compileCoroutine, CoroutineReturnValueRef<typename TCoroutine::ReturnValue_t>::isVoid(),
typename TCoroutine::Params(Common::forward<TParams>(args)...), CoroutineReturnValueRef<typename TCoroutine::ReturnValue_t>(returnValuePtr));
251template<
typename TCoroutine,
typename TReturnValue>
252void VThread::pushCoroutineWithReturn(TReturnValue *returnValuePtr) {
253 assert(returnValuePtr !=
nullptr);
254 this->pushCoroutineInternal(&TCoroutine::ms_compiledCoro, TCoroutine::compileCoroutine, CoroutineReturnValueRef<typename TCoroutine::ReturnValue_t>::isVoid(),
typename TCoroutine::Params(), CoroutineReturnValueRef<typename TCoroutine::ReturnValue_t>(returnValuePtr));
257template<
typename TCoroutine,
typename... TParams>
258void VThread::pushCoroutine(TParams &&...args) {
259 this->pushCoroutineInternal(&TCoroutine::ms_compiledCoro, TCoroutine::compileCoroutine, CoroutineReturnValueRef<typename TCoroutine::ReturnValue_t>::isVoid(),
typename TCoroutine::Params(Common::forward<TParams>(args)...), CoroutineReturnValueRef<typename TCoroutine::ReturnValue_t>());
262template<
typename TCoroutine>
263void VThread::pushCoroutine() {
264 this->pushCoroutineInternal(&TCoroutine::ms_compiledCoro, TCoroutine::compileCoroutine, CoroutineReturnValueRef<typename TCoroutine::ReturnValue_t>::isVoid(),
typename TCoroutine::Params(), CoroutineReturnValueRef<typename TCoroutine::ReturnValue_t>());
267template<
typename TClass,
typename TData>
268TData *VThread::pushTask(
const char *name, TClass *obj, VThreadState (TClass::*method)(
const TData &data)) {
269 return this->pushTaskWithFaultHandler(
nullptr, name, obj, method);
272template<
typename TData>
273TData *VThread::pushTask(
const char *name, VThreadState (*func)(
const TData &data)) {
274 return this->pushTaskWithFaultHandler(
nullptr, name, func);
277template<
typename TClass,
typename TData>
278TData *VThread::pushTaskWithFaultHandler(
const VThreadFaultIdentifier *faultID,
const char *name, TClass *obj, VThreadState (TClass::*method)(
const TData &data)) {
279 typedef VThreadMethodData<TClass, TData> FrameData_t;
281 const size_t frameAlignment =
alignof(VThreadStackFrame);
282 const size_t dataAlignment =
alignof(FrameData_t);
284 VThreadStackFrame *prevFrame =
nullptr;
285 if (_numActiveStackChunks > 0)
286 prevFrame = _stackChunks[_numActiveStackChunks - 1]._topFrame;
288 VThreadStackFrame *framePtr =
nullptr;
289 void *dataPtr =
nullptr;
290 bool isNewChunk =
false;
291 reserveFrame(frameAlignment,
sizeof(VThreadStackFrame), framePtr, dataAlignment,
sizeof(FrameData_t), dataPtr, isNewChunk);
293 VThreadStackFrame *frame =
new (framePtr) VThreadStackFrame();
294 FrameData_t *frameData =
new (dataPtr) FrameData_t(faultID, obj, method);
296 frame->data = frameData;
297 frame->prevFrame = prevFrame;
298 frame->isLastInChunk = isNewChunk;
300#ifdef MTROPOLIS_DEBUG_ENABLE
301 frameData->debugInit(name);
304 return &frameData->getData();
307template<
typename TData>
308TData *VThread::pushTaskWithFaultHandler(
const VThreadFaultIdentifier *faultID,
const char *name, VThreadState (*func)(
const TData &data)) {
309 typedef VThreadFunctionData<TData> FrameData_t;
311 const size_t frameAlignment =
alignof(VThreadStackFrame);
312 const size_t dataAlignment =
alignof(FrameData_t);
314 VThreadStackFrame *prevFrame =
nullptr;
315 if (_numActiveStackChunks > 0)
316 prevFrame = _stackChunks[_numActiveStackChunks - 1]._topFrame;
318 VThreadStackFrame *framePtr =
nullptr;
319 void *dataPtr =
nullptr;
320 bool isNewChunk =
false;
321 reserveFrame(frameAlignment,
sizeof(VThreadStackFrame), framePtr, dataAlignment,
sizeof(FrameData_t), dataPtr, isNewChunk);
323 VThreadStackFrame *frame =
new (framePtr) VThreadStackFrame();
324 FrameData_t *frameData =
new (dataPtr) FrameData_t(faultID, func);
326 frame->data = frameData;
327 frame->prevFrame = prevFrame;
328 frame->isLastInChunk = isNewChunk;
330#ifdef MTROPOLIS_DEBUG_ENABLE
331 frameData->debugInit(name);
334 return &frameData->getData();
Definition: vthread.h:115
Definition: vthread.h:133
Definition: coroutines.h:50
Definition: coroutine_protos.h:42
Definition: coroutine_return_value.h:27
Definition: coroutine_manager.h:34