code size and performance optimizations (#472)
* Clean-up EntityManager a bit - use tsl::robin_set instead of std::set (which should have been unordered::set anyways). - getListeners() now returns a vector which avoids to traverse a set twice. Turns out that copying the set wasn't as efficient as I thought. * Improve jobsystem a bit We recently added a job reference counting mechanism, but we were a bit too aggressive about taking/release references. Also make the API more complete by adding explicit retain/release, which is needed to allow several threads to wait on the same job. Also improve futex code by inlining it.
This commit is contained in:
@@ -216,39 +216,78 @@ public:
|
||||
return job;
|
||||
}
|
||||
|
||||
// Add job to this thread's execution queue.
|
||||
// Current thread must be owned by JobSystem's thread pool. See adopt().
|
||||
|
||||
/*
|
||||
* Jobs are normally finished automatically, this can be used to cancel a job before it is run.
|
||||
*
|
||||
* Never use this once a flavor of run() has been called.
|
||||
*/
|
||||
void cancel(Job*& job) noexcept;
|
||||
|
||||
/*
|
||||
* Adds a reference to a Job.
|
||||
*
|
||||
* This allows the caller to waitAndRelease() on this job from multiple threads.
|
||||
* Use runAndWait() if waiting from multiple threads is not needed.
|
||||
*
|
||||
* This job MUST BE waited on with waitAndRelease(), or released with release().
|
||||
*/
|
||||
Job* retain(Job* job) noexcept;
|
||||
|
||||
/*
|
||||
* Releases a reference from a Job obtained with runAndRetain() or a call to retain().
|
||||
*
|
||||
* The job can't be used after this call.
|
||||
*/
|
||||
void release(Job*& job) noexcept;
|
||||
void release(Job*&& job) noexcept {
|
||||
Job* p = job;
|
||||
release(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add job to this thread's execution queue. It's reference will drop automatically.
|
||||
* Current thread must be owned by JobSystem's thread pool. See adopt().
|
||||
*
|
||||
* The job can't be used after this call.
|
||||
*/
|
||||
enum runFlags { DONT_SIGNAL = 0x1 };
|
||||
void run(Job*& job, uint32_t flags = 0) noexcept;
|
||||
|
||||
// This version allow a call such as run(createJob(...));
|
||||
void run(Job*&& job, uint32_t flags = 0) noexcept {
|
||||
void run(Job*&& job, uint32_t flags = 0) noexcept { // allows run(createJob(...));
|
||||
Job* p = job;
|
||||
run(p);
|
||||
}
|
||||
|
||||
// run a job and keep a reference to it. This job MUST BE waited on with wait().
|
||||
/*
|
||||
* Add job to this thread's execution queue and and keep a reference to it.
|
||||
* Current thread must be owned by JobSystem's thread pool. See adopt().
|
||||
*
|
||||
* This job MUST BE waited on with wait(), or released with release().
|
||||
*/
|
||||
Job* runAndRetain(Job* job, uint32_t flags = 0) noexcept;
|
||||
|
||||
// Wait on a job and destroys it. The job must first be obtained from runAndRetain().
|
||||
// Current thread must be owned by JobSystem's thread pool. See adopt().
|
||||
void wait(Job*& job) noexcept;
|
||||
/*
|
||||
* Wait on a job and destroys it.
|
||||
* Current thread must be owned by JobSystem's thread pool. See adopt().
|
||||
*
|
||||
* The job must first be obtained from runAndRetain() or retain().
|
||||
* The job can't be used after this call.
|
||||
*/
|
||||
void waitAndRelease(Job*& job) noexcept;
|
||||
|
||||
void runAndWait(Job*& job) noexcept {
|
||||
runAndRetain(job);
|
||||
wait(job);
|
||||
}
|
||||
|
||||
// This version allow a call such as runAndWait(createJob(...));
|
||||
void runAndWait(Job*&& job) noexcept {
|
||||
/*
|
||||
* Runs and wait for a job. This is equivalent to calling
|
||||
* runAndRetain(job);
|
||||
* wait(job);
|
||||
*
|
||||
* The job can't be used after this call.
|
||||
*/
|
||||
void runAndWait(Job*& job) noexcept;
|
||||
void runAndWait(Job*&& job) noexcept { // allows runAndWait(createJob(...));
|
||||
Job* p = job;
|
||||
runAndWait(p);
|
||||
}
|
||||
|
||||
// jobs are normally finished automatically, this can be used to cancel a job
|
||||
// before it is run.
|
||||
void finish(Job* job) noexcept;
|
||||
|
||||
// for debugging
|
||||
friend utils::io::ostream& operator << (utils::io::ostream& out, JobSystem const& js);
|
||||
|
||||
@@ -297,18 +336,6 @@ private:
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
class Pin {
|
||||
JobSystem& js;
|
||||
Job const* job;
|
||||
public:
|
||||
Pin(JobSystem& js, Job const* job) noexcept : js(js), job(job) {
|
||||
js.incRef(job);
|
||||
}
|
||||
~Pin() noexcept {
|
||||
js.decRef(job);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(ThreadState) % CACHELINE_SIZE == 0,
|
||||
"ThreadState doesn't align to a cache line");
|
||||
|
||||
@@ -327,6 +354,7 @@ private:
|
||||
|
||||
void loop(ThreadState* threadState) noexcept;
|
||||
bool execute(JobSystem::ThreadState& state) noexcept;
|
||||
void finish(Job* job) noexcept;
|
||||
|
||||
void put(WorkQueue& workQueue, Job* job) noexcept {
|
||||
size_t index = job - mJobStorageBase;
|
||||
|
||||
Reference in New Issue
Block a user