-
Notifications
You must be signed in to change notification settings - Fork 38
Concurrency primitives #1052
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Concurrency primitives #1052
Conversation
94f661d
to
6a24a05
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR replaces the old promise-based implementation in C and Effekt with a channel-based API, renames the wait
function to sleep
in the time library, and updates example imports accordingly.
- Switch C-side
Promise
toChannel
with statesEMPTY
,SENDED
,WAITED
- Rename
extern async def wait
tosleep
inio/time.effekt
- Add new
io/channel
andio/promise
Effekt modules and update examples
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
File | Description |
---|---|
libraries/llvm/io.c | Replaced Promise struct and functions with Channel |
libraries/common/io/time.effekt | Renamed wait to sleep in time API |
libraries/common/io/promise.effekt | Added new Effekt promise module |
libraries/common/io/channel.effekt | Added new Effekt channel module |
libraries/common/io.effekt | Removed old promise code, slimmed imports |
examples/stdlib/io/time.effekt | Updated example to use sleep |
examples/stdlib/io/promise.effekt | Added import io/promise |
examples/stdlib/io/filesystem/... | Added import io/promise |
examples/stdlib/acme.effekt | Added import io/channel & io/promise |
examples/benchmarks/.../interleave_promises.effekt | Added import io/promise |
Comments suppressed due to low confidence (1)
libraries/llvm/io.c:301
- The state name 'SENDED' is grammatically incorrect; consider renaming it to 'SENT' to improve clarity.
typedef enum { EMPTY, SENDED, WAITED } channel_state_t;
libraries/llvm/io.c
Outdated
void c_channel_send(struct Pos channel, struct Pos value) { | ||
Channel* f = (Channel*)channel.obj; | ||
switch (f->state) { | ||
case EMPTY: { | ||
f->state = SENDED; | ||
f->payload.value = value; | ||
erasePositive(channel); | ||
break; | ||
case RESOLVED: | ||
erasePositive(promise); | ||
} | ||
case SENDED: { | ||
erasePositive(channel); | ||
erasePositive(value); | ||
eraseStack(stack); | ||
fprintf(stderr, "ERROR: Promise already resolved\n"); | ||
// TODO more graceful panic | ||
fprintf(stderr, "ERROR: Channel already sended\n"); | ||
exit(1); | ||
break; | ||
} | ||
case WAITED: { | ||
Stack stack = f->payload.stack; | ||
f->state = EMPTY; | ||
erasePositive(channel); | ||
resume_Pos(stack, value); | ||
break; | ||
} | ||
} | ||
// TODO stack overflow? | ||
// We need to erase the promise now, since we consume it. | ||
erasePositive(promise); | ||
} | ||
|
||
void c_promise_await(struct Pos promise, Stack stack) { | ||
Promise* p = (Promise*)promise.obj; | ||
|
||
Stack head; | ||
Listeners* tail; | ||
Listeners* node; | ||
struct Pos value; | ||
|
||
switch (p->state) { | ||
case UNRESOLVED: | ||
head = p->payload.listeners.head; | ||
tail = p->payload.listeners.tail; | ||
if (head != NULL) { | ||
node = (Listeners*)malloc(sizeof(Listeners)); | ||
node->head = head; | ||
node->tail = tail; | ||
p->payload.listeners.head = stack; | ||
p->payload.listeners.tail = node; | ||
} else { | ||
p->payload.listeners.head = stack; | ||
}; | ||
void c_channel_wait(struct Pos channel, Stack stack) { | ||
Channel* f = (Channel*)channel.obj; | ||
switch (f->state) { | ||
case EMPTY: { | ||
f->state = WAITED; | ||
f->payload.stack = stack; | ||
erasePositive(channel); | ||
break; | ||
case RESOLVED: | ||
value = p->payload.value; | ||
sharePositive(value); | ||
} | ||
case SENDED: { | ||
struct Pos value = f->payload.value; | ||
f->state = EMPTY; | ||
erasePositive(channel); | ||
resume_Pos(stack, value); | ||
break; | ||
}; | ||
// TODO hmm, stack overflow? | ||
erasePositive(promise); | ||
} | ||
|
||
struct Pos c_promise_make() { | ||
Promise* promise = (Promise*)malloc(sizeof(Promise)); | ||
|
||
promise->rc = 0; | ||
promise->eraser = c_promise_erase_listeners; | ||
promise->state = UNRESOLVED; | ||
promise->payload.listeners.head = NULL; | ||
promise->payload.listeners.tail = NULL; | ||
|
||
return (struct Pos) { .tag = 0, .obj = promise, }; | ||
} | ||
case WAITED: { | ||
erasePositive(channel); | ||
eraseStack(stack); | ||
// TODO more graceful panic | ||
fprintf(stderr, "ERROR: Channel already waited\n"); | ||
exit(1); | ||
break; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a TODO for a more graceful panic; consider implementing structured error handling rather than calling exit directly.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is C and this is an assertion violation.
libraries/llvm/io.c
Outdated
} | ||
case SENDED: { | ||
struct Pos value = f->payload.value; | ||
f->state = EMPTY; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the SENDED branch of c_channel_wait, erasing the channel after setting its state to EMPTY prevents payload.value from being freed, leading to a memory leak. Consider explicitly erasing the value or adjusting the state before erasing.
f->state = EMPTY; | |
f->state = EMPTY; | |
erasePositive(value); |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nono, the value is moved!
b383f2a
to
6cb85be
Compare
No description provided.