Return pointer to next function

This commit is contained in:
2024-09-09 21:59:49 -07:00
parent 4b8f7320d3
commit 867136ff1b

View File

@@ -8,16 +8,18 @@
struct Job { struct Job {
int *input; int *input;
bool (*next)(Job *); // Returned void* is a function pointer to the next continuation. We have to
// use void* because otherwise the type would be recursive.
typedef void *(*continuation)(Job *);
continuation next;
}; };
bool stepJob(Job *j) { void *stepJob(Job *j) {
auto &val = *j->input; auto done = --(*j->input) == 0;
auto result = --val == 0;
#ifdef __x86_64__ #ifdef __x86_64__
_mm_clflush(j->input); _mm_clflush(j->input);
#endif #endif
return result; return done ? nullptr : (void *)stepJob;
} }
// So we can look at the disassembly more easily // So we can look at the disassembly more easily
@@ -25,14 +27,15 @@ bool stepJob(Job *j) {
extern "C" { extern "C" {
void sequential(Job **jobs, int count) { void sequential(Job **jobs, int count) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
while (!jobs[i]->next(jobs[i])) do {
; jobs[i]->next = (Job::continuation)jobs[i]->next(jobs[i]);
} while (jobs[i]->next);
} }
} }
void sequentialNoFuncPtr(Job **jobs, int count) { void sequentialNoFuncPtr(Job **jobs, int count) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
while (!stepJob(jobs[i])) while (stepJob(jobs[i]))
; ;
} }
} }
@@ -40,8 +43,9 @@ void sequentialNoFuncPtr(Job **jobs, int count) {
void interleaveSwapping(Job **jobs, int remaining) { void interleaveSwapping(Job **jobs, int remaining) {
int current = 0; int current = 0;
while (remaining > 0) { while (remaining > 0) {
bool done = jobs[current]->next(jobs[current]); auto next = (Job::continuation)jobs[current]->next(jobs[current]);
if (done) { jobs[current]->next = next;
if (next == nullptr) {
jobs[current] = jobs[remaining - 1]; jobs[current] = jobs[remaining - 1];
--remaining; --remaining;
} else { } else {
@@ -72,8 +76,9 @@ void interleaveBoundedCyclicList(Job **jobs, int count) {
int prevJob = started - 1; int prevJob = started - 1;
int job = 0; int job = 0;
for (;;) { for (;;) {
bool done = inProgress[job]->next(inProgress[job]); auto next = (Job::continuation)inProgress[job]->next(inProgress[job]);
if (done) { inProgress[job]->next = next;
if (next == nullptr) {
if (started == count) { if (started == count) {
if (prevJob == job) if (prevJob == job)
break; break;
@@ -100,8 +105,9 @@ void interleaveCyclicList(Job **jobs, int count) {
int prevJob = count - 1; int prevJob = count - 1;
int job = 0; int job = 0;
for (;;) { for (;;) {
bool done = jobs[job]->next(jobs[job]); auto next = (Job::continuation)jobs[job]->next(jobs[job]);
if (done) { jobs[job]->next = next;
if (next == nullptr) {
if (prevJob == job) if (prevJob == job)
break; break;
nextJob[prevJob] = nextJob[job]; nextJob[prevJob] = nextJob[job];