#ifdef _MULTITHREADED class CoWork : NoCopy { struct MJob : Moveable, Link { Function fn; CoWork *work = NULL; }; enum { SCHEDULED_MAX = 2048 }; public: struct Pool { MJob *free; Link jobs; MJob slot[SCHEDULED_MAX]; int waiting_threads; Array threads; bool quit; Mutex lock; ConditionVariable waitforjob; void Free(MJob& m); void DoJob(MJob& m); void PushJob(Function&& fn, CoWork *work); void InitThreads(int nthreads); void ExitThreads(); Pool(); ~Pool(); static thread__ bool finlock; bool DoJob(); static void ThreadRun(int tno); }; friend struct Pool; static Pool& GetPool(); static thread_local int worker_index; ConditionVariable waitforfinish; Link jobs; // global stack and CoWork stack as double-linked lists int todo; // experimental pipe support Mutex stepmutex; Array>> step; Vector steprunning; public: static bool TrySchedule(Function&& fn); static bool TrySchedule(const Function& fn) { return TrySchedule(clone(fn)); } static void Schedule(Function&& fn); static void Schedule(const Function& fn) { return Schedule(clone(fn)); } void Do(Function&& fn); void Do(const Function& fn) { Do(clone(fn)); } CoWork& operator&(const Function& fn) { Do(fn); return *this; } CoWork& operator&(Function&& fn) { Do(pick(fn)); return *this; } void Pipe(int stepi, Function&& lambda); // experimental static void FinLock(); void Finish(); bool IsFinished(); static bool IsWorker() { return worker_index >= 0; } static int GetWorkerIndex() { return worker_index; } static int GetPoolSize(); static void SetPoolSize(int n); CoWork(); ~CoWork(); }; template class CoWorkerResources { int workercount; Buffer res; public: int GetCount() const { return workercount + 1; } T& operator[](int i) { return res[i]; } T& Get() { int i = CoWork::GetWorkerIndex(); return res[i < 0 ? workercount : i]; } T& operator~() { return Get(); } T *begin() { return ~res; } T *end() { return ~res + GetCount(); } CoWorkerResources() { workercount = CoWork::GetPoolSize(); res.Alloc(GetCount()); } CoWorkerResources(Event initializer) : CoWorkerResources() { for(int i = 0; i < GetCount(); i++) initializer(res[i]); } }; #else class CoWork : NoCopy { public: void Do(Event<> cb) { cb(); } CoWork& operator&(Event<> cb) { cb(); return *this; } void Finish() {} bool IsFinished() { return true; } static void FinLock() {} static bool IsWorker() { return false; } static void StartPool(int n) {} static void ShutdownPool() {} }; #endif