24#define JOB_SIGNATURE (SizeT totalJobs, SizeT groupSize, IndexT groupIndex, SizeT invocationOffset)
25#define JOB_BEGIN_LOOP \
26for (IndexT i = 0; i < groupSize; i++)\
28 IndexT __INDEX = i + invocationOffset;\
29 if (__INDEX >= totalJobs)\
35#define JOB_ITEM_INDEX __INDEX
44template <
typename... ARGS>
48 virtual void invoke(ARGS... args) = 0;
51template<
typename LAMBDA,
typename... ARGS>
69 template<
typename LAMBDA>
74 new (this->callable) CallableType(l);
79 callable->
invoke(totalJobs, groupSize, groupIndex, invocationOffset);
85 this->callable->~Stub();
86 this->callable =
nullptr;
149 virtual void DoWork()
override;
199 , Threading::Event* signalEvent =
nullptr);
204 ,
const SizeT numInvocations
205 ,
const SizeT groupSize
212 ,
const SizeT numInvocations
219 ,
const SizeT numInvocations
220 ,
const SizeT groupSize
225 ,
const SizeT numInvocations
234template <
typename T> T*
237 return (T*)
JobAlloc(count *
sizeof(T));
243template <
typename LAMBDA>
void
246 ,
const SizeT numInvocations
247 ,
const SizeT groupSize
250 , Threading::Event* signalEvent =
nullptr
253 if (numInvocations == 0)
255 if (doneCounter !=
nullptr)
257 doneCounter->Exchange(0);
260 if (signalEvent !=
nullptr)
262 signalEvent->Signal();
266 n_assert(doneCounter !=
nullptr ? *doneCounter > 0 :
true);
277 node->job.waitCounters =
nullptr;
278 if (waitCounters.Size() > 0)
284 node->job.l = std::move(func);
285 node->job.func =
nullptr;
286 node->job.remainingGroups = numJobs;
287 node->job.groupCompletionCounter = numJobs;
288 node->job.numInvocations = numInvocations;
289 node->job.groupSize = groupSize;
290 node->job.numWaitCounters = (
SizeT)waitCounters.Size();
291 node->job.doneCounter = doneCounter;
292 node->job.signalEvent = signalEvent;
293 node->sequence =
nullptr;
303 node->
next =
nullptr;
313 thread->SignalWorkAvailable();
320template <
typename LAMBDA>
void
323 ,
const SizeT numInvocations
326 , Threading::Event* signalEvent =
nullptr
329 JobDispatch(func, numInvocations, numInvocations, waitCounters, doneCounter, signalEvent);
335template <
typename CTX>
void
338 ,
const SizeT numInvocations
339 ,
const SizeT groupSize
343 , Threading::Event* signalEvent =
nullptr
346 static_assert(std::is_trivially_destructible<CTX>::value,
"Job context has to be trivially destructible");
348 n_assert(doneCounter !=
nullptr ? *doneCounter > 0 :
true);
359 node->job.waitCounters =
nullptr;
360 if (waitCounters.Size() > 0)
367 node->job.data = (
void*)(mem +
sizeof(
JobNode));
368 auto data =
reinterpret_cast<CTX*
>(node->job.data);
371 node->job.l.callable =
nullptr;
372 node->job.func = func;
373 node->job.remainingGroups = numJobs;
374 node->job.groupCompletionCounter = numJobs;
375 node->job.numInvocations = numInvocations;
376 node->job.groupSize = groupSize;
377 node->job.numWaitCounters = (
SizeT)waitCounters.Size();
378 node->job.doneCounter = doneCounter;
379 node->job.signalEvent = signalEvent;
380 node->sequence =
nullptr;
390 node->
next =
nullptr;
400 thread->SignalWorkAvailable();
407template <
typename CTX>
void
410 ,
const SizeT numInvocations
414 , Threading::Event* signalEvent =
nullptr
417 JobDispatch(func, numInvocations, numInvocations, context, waitCounters, doneCounter, signalEvent);
423template<
typename CTX>
void
426 static_assert(std::is_trivially_destructible<CTX>::value,
"Job context has to be trivially destructible");
443 node->job.numWaitCounters = 1;
449 node->job.numWaitCounters = 0;
450 node->job.waitCounters =
nullptr;
454 node->job.data = (
void*)(mem +
sizeof(
JobNode));
455 auto data =
reinterpret_cast<CTX*
>(node->job.data);
458 node->job.l.callable =
nullptr;
459 node->job.func = func;
460 node->job.remainingGroups = numJobs;
461 node->job.groupCompletionCounter = numJobs;
462 node->job.numInvocations = numInvocations;
463 node->job.groupSize = groupSize;
466 *node->job.doneCounter = 1;
468 node->job.signalEvent =
nullptr;
469 node->next =
nullptr;
486template<
typename CTX>
void
495template<
typename LAMBDA>
void
498 const SizeT numInvocations,
499 const SizeT groupSize
533 node->job.numWaitCounters = 1;
539 node->job.numWaitCounters = 0;
540 node->job.waitCounters =
nullptr;
544 node->job.l = std::move(func);
545 node->job.func =
nullptr;
546 node->job.remainingGroups = numJobs;
547 node->job.groupCompletionCounter = numJobs;
548 node->job.numInvocations = numInvocations;
549 node->job.groupSize = groupSize;
552 *node->job.doneCounter = 1;
554 node->job.signalEvent =
nullptr;
555 node->next =
nullptr;
572template<
typename LAMBDA>
void
JobThread()
constructor
Definition jobs2.cc:19
virtual void DoWork() override
this method runs in the thread context
Definition jobs2.cc:58
Threading::Event wakeupEvent
Definition jobs2.h:152
void SignalWorkAvailable()
Signal new work available.
Definition jobs2.cc:40
__DeclareClass(JobThread)
virtual void EmitWakeupSignal() override
override this method if your thread loop needs a wakeup call before stopping
Definition jobs2.cc:49
bool enableProfiling
Definition jobs2.h:143
bool enableIo
Definition jobs2.h:142
Nebula's smart pointer class which manages the life time of RefCounted objects.
Definition ptr.h:38
Nebula's dynamic array class.
Definition array.h:61
Implements a fixed size one-dimensional array.
Definition fixedarray.h:20
A StringAtom.
Definition stringatom.h:22
#define n_assert(exp)
Definition debug.h:58
const Threading::Interlocked::AtomicCounter * prevDoneCounter
Definition jobs2.cc:301
void JobBeginSequence(const Util::FixedArray< const Threading::Interlocked::AtomicCounter *, true > &waitCounters, Threading::Interlocked::AtomicCounter *doneCounter, Threading::Event *signalEvent)
Begin a sequence of jobs.
Definition jobs2.cc:308
Threading::ThreadId sequenceThread
Definition jobs2.cc:302
Jobs2Context ctx
Definition jobs2.cc:13
Jobs2::JobNode * sequenceNode
Definition jobs2.cc:299
Jobs2::JobNode * sequenceTail
Definition jobs2.cc:300
void JobEndSequence(Threading::Event *signalEvent)
Flush queued jobs.
Definition jobs2.cc:349
void(*)(SizeT totalJobs, SizeT groupSize, IndexT groupIndex, SizeT invocationOffset, void *ctx) JobFunc
Definition jobs2.h:42
void JobSystemUninit()
Destroy job port.
Definition jobs2.cc:245
void JobDispatch(LAMBDA &&func, const SizeT numInvocations, const SizeT groupSize, const Util::FixedArray< const Threading::Interlocked::AtomicCounter *, true > &waitCounters=nullptr, Threading::Interlocked::AtomicCounter *doneCounter=nullptr, Threading::Event *signalEvent=nullptr)
Definition jobs2.h:244
void * JobAlloc(SizeT bytes)
Allocate memory.
Definition jobs2.cc:269
void JobSystemInit(const JobSystemInitInfo &info)
Create a new job port.
Definition jobs2.cc:212
volatile long CompletionCounter
Definition jobs2.h:41
void JobNewFrame()
Progress to new buffer.
Definition jobs2.cc:258
void JobAppendSequence(const JobFunc &func, const SizeT numInvocations, const SizeT groupSize, const CTX &context)
Append job to sequence with an automatic dependency on the previous job.
Definition jobs2.h:424
__forceinline float ceil(float val)
Floating point ceiling.
Definition scalar.h:542
The Jobs2 system provides a set of threads and a pool of jobs from which threads can pickup work.
Definition jobs2.h:16
pthread_t ThreadId
Definition linuxthreadid.h:15
LAMBDA l
Definition jobs2.h:54
void invoke(ARGS... args) override
Definition jobs2.h:58
Callable(LAMBDA l)
Definition jobs2.h:56
virtual ~CallableStub()=default
virtual void invoke(ARGS... args)=0
const Threading::Interlocked::AtomicCounter ** waitCounters
Definition jobs2.h:99
void * data
Definition jobs2.h:98
SizeT groupSize
Definition jobs2.h:97
Threading::Interlocked::AtomicCounter * doneCounter
Definition jobs2.h:101
int remainingGroups
Definition jobs2.h:94
SizeT numWaitCounters
Definition jobs2.h:100
Threading::Interlocked::AtomicCounter groupCompletionCounter
Definition jobs2.h:95
SizeT numInvocations
Definition jobs2.h:96
Threading::Event * signalEvent
Definition jobs2.h:102
JobFunc func
Definition jobs2.h:92
Lambda l
Definition jobs2.h:93
JobNode * next
Definition jobs2.h:107
JobContext job
Definition jobs2.h:108
JobNode * sequence
Definition jobs2.h:109
uint priority
Definition jobs2.h:160
bool enableIo
Definition jobs2.h:165
SizeT scratchMemorySize
Definition jobs2.h:162
Util::StringAtom name
Definition jobs2.h:157
uint affinity
Definition jobs2.h:159
JobSystemInitInfo()
Definition jobs2.h:168
SizeT numThreads
Definition jobs2.h:158
bool enableProfiling
Definition jobs2.h:166
SizeT numBuffers
Definition jobs2.h:163
IndexT activeBuffer
Definition jobs2.h:122
JobNode * head
Definition jobs2.h:115
Util::Array< JobNode * > queuedJobs
Definition jobs2.h:118
SizeT scratchMemorySize
Definition jobs2.h:124
IndexT iterator
Definition jobs2.h:121
SizeT numBuffers
Definition jobs2.h:120
Util::FixedArray< byte * > scratchMemory
Definition jobs2.h:123
JobNode * tail
Definition jobs2.h:116
Util::FixedArray< Ptr< JobThread > > threads
Definition jobs2.h:117
Threading::CriticalSection jobLock
Definition jobs2.h:114
void Destroy()
destroy the captured state, the memory itself belongs to the job scratch buffer
Definition jobs2.h:83
Lambda(LAMBDA l)
Definition jobs2.h:70
Stub * callable
Definition jobs2.h:67
void operator()(SizeT totalJobs, SizeT groupSize, IndexT groupIndex, SizeT invocationOffset)
Definition jobs2.h:77
CallableStub< SizeT, SizeT, IndexT, SizeT > Stub
Definition jobs2.h:66
Atomic value only used to decrement, increment and read a 32 bit value.
Definition interlocked.h:214
int SizeT
Definition types.h:42
unsigned int uint
Definition types.h:33
int IndexT
Definition types.h:41