Skip to content

Commit 6a24a05

Browse files
committed
Rename and move futures to channels
1 parent 9229d49 commit 6a24a05

File tree

5 files changed

+81
-75
lines changed

5 files changed

+81
-75
lines changed

examples/stdlib/acme.effekt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import effekt
1313
import exception
1414
import heap
1515
import io
16+
import io/channel
1617
import io/console
1718
import io/error
1819
import io/filesystem

libraries/common/io.effekt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
module io
22

3-
import ref
43

54
// Event Loop
65
// ----------

libraries/common/io/channel.effekt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module io/channel
2+
3+
// Channels
4+
// --------
5+
6+
/// Must be sended exactly once and waited exactly once
7+
extern type Channel[T]
8+
9+
namespace channel {
10+
extern global def allocate[T](): Channel[T] =
11+
llvm """
12+
%channel = call %Pos @c_channel_make()
13+
ret %Pos %channel
14+
"""
15+
}
16+
17+
extern global def send[T](channel: Channel[T], value: T): Unit =
18+
llvm """
19+
call void @c_channel_send(%Pos ${channel}, %Pos ${value})
20+
ret %Pos zeroinitializer
21+
"""
22+
23+
extern async def wait[T](channel: Channel[T]): T =
24+
llvm """
25+
call void @c_channel_wait(%Pos ${channel}, %Stack %stack)
26+
ret void
27+
"""
28+
29+
extern llvm """
30+
declare %Pos @c_channel_make()
31+
declare void @c_channel_send(%Pos, %Pos)
32+
declare void @c_channel_wait(%Pos, %Stack)
33+
"""
34+
35+
36+
37+

libraries/common/io/promise.effekt

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,14 @@
11
module io/promise
22

33
import io
4-
5-
// Futures
6-
// -------
7-
8-
/// Must be filled exactly once and waited exactly once
9-
extern type Future[T]
10-
11-
namespace future {
12-
extern global def allocate[T](): Future[T] =
13-
llvm """
14-
%future = call %Pos @c_future_make()
15-
ret %Pos %future
16-
"""
17-
}
18-
19-
extern global def fill[T](future: Future[T], value: T): Unit =
20-
llvm """
21-
call void @c_future_fill(%Pos ${future}, %Pos ${value})
22-
ret %Pos zeroinitializer
23-
"""
24-
25-
extern async def wait[T](future: Future[T]): T =
26-
llvm """
27-
call void @c_future_wait(%Pos ${future}, %Stack %stack)
28-
ret void
29-
"""
30-
31-
extern llvm """
32-
declare %Pos @c_future_make()
33-
declare void @c_future_fill(%Pos, %Pos)
34-
declare void @c_future_wait(%Pos, %Stack)
35-
"""
4+
import io/channel
365

376
// Promises
387
// --------
398

409
type State[T] {
4110
Resolved(value: T)
42-
Pending(futures: List[Future[T]])
11+
Pending(channels: List[Channel[T]])
4312
}
4413

4514
extern type Promise[T]
@@ -76,11 +45,11 @@ extern {async, global} def await[T](promise: Promise[T]): T =
7645
get(reference) match {
7746
case Resolved(value) =>
7847
return value
79-
case Pending(futures) =>
80-
val future = future::allocate()
81-
// TODO use reference.set and future.wait
82-
set(reference, Pending(Cons(future, futures)))
83-
wait(future)
48+
case Pending(channels) =>
49+
val channel = channel::allocate()
50+
// TODO use reference.set and channel.wait
51+
set(reference, Pending(Cons(channel, channels)))
52+
wait(channel)
8453
}
8554
}
8655

@@ -92,11 +61,11 @@ extern {io, global} def resolve[T](promise: Promise[T], value: T): Unit =
9261
get(reference) match {
9362
case Resolved(value) =>
9463
panic("ERROR: Promise already resolved")
95-
case Pending(futures) =>
64+
case Pending(channels) =>
9665
// TODO use reference.set
9766
set(reference, Resolved(value))
98-
// TODO use futures.reverse.foreach
99-
foreach(reverse(futures)) { future => fill(future, value) }
67+
// TODO use channels.reverse.foreach
68+
foreach(reverse(channels)) { channel => send(channel, value) }
10069
}
10170
}
10271

libraries/llvm/io.c

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -295,95 +295,95 @@ void c_yield(Stack stack) {
295295
c_timer_start(0, stack);
296296
}
297297

298-
// Futures
299-
// -------
298+
// Channels
299+
// --------
300300

301-
typedef enum { EMPTY, FILLED, WAITED } future_state_t;
301+
typedef enum { EMPTY, SENDED, WAITED } channel_state_t;
302302

303303
typedef struct {
304304
uint64_t rc;
305305
void* eraser;
306-
future_state_t state;
306+
channel_state_t state;
307307
union {
308308
struct Pos value;
309309
Stack stack;
310310
} payload;
311-
} Future;
311+
} Channel;
312312

313-
void c_future_erase(void *envPtr) {
314-
// envPtr points to a Future _after_ the eraser, so let's adjust it to point to the beginning.
315-
Future *future = (Future*) (envPtr - offsetof(Future, state));
316-
future_state_t state = future->state;
313+
void c_channel_erase(void *envPtr) {
314+
// envPtr points to a Channel _after_ the eraser, so let's adjust it to point to the beginning.
315+
Channel *channel = (Channel*) (envPtr - offsetof(Channel, state));
316+
channel_state_t state = channel->state;
317317
switch (state) {
318318
case EMPTY:
319319
break;
320-
case FILLED:
321-
erasePositive(future->payload.value);
320+
case SENDED:
321+
erasePositive(channel->payload.value);
322322
break;
323323
case WAITED:
324-
eraseStack(future->payload.stack);
324+
eraseStack(channel->payload.stack);
325325
break;
326326
}
327327
}
328328

329-
struct Pos c_future_make() {
330-
Future* future = (Future*)malloc(sizeof(Future));
329+
struct Pos c_channel_make() {
330+
Channel* channel = (Channel*)malloc(sizeof(Channel));
331331

332-
future->rc = 0;
333-
future->eraser = c_future_erase;
334-
future->state = EMPTY;
332+
channel->rc = 0;
333+
channel->eraser = c_channel_erase;
334+
channel->state = EMPTY;
335335

336-
return (struct Pos) { .tag = 0, .obj = future, };
336+
return (struct Pos) { .tag = 0, .obj = channel, };
337337
}
338338

339-
void c_future_fill(struct Pos future, struct Pos value) {
340-
Future* f = (Future*)future.obj;
339+
void c_channel_send(struct Pos channel, struct Pos value) {
340+
Channel* f = (Channel*)channel.obj;
341341
switch (f->state) {
342342
case EMPTY: {
343-
f->state = FILLED;
343+
f->state = SENDED;
344344
f->payload.value = value;
345-
erasePositive(future);
345+
erasePositive(channel);
346346
break;
347347
}
348-
case FILLED: {
349-
erasePositive(future);
348+
case SENDED: {
349+
erasePositive(channel);
350350
erasePositive(value);
351351
// TODO more graceful panic
352-
fprintf(stderr, "ERROR: Future already filled\n");
352+
fprintf(stderr, "ERROR: Channel already sended\n");
353353
exit(1);
354354
break;
355355
}
356356
case WAITED: {
357357
Stack stack = f->payload.stack;
358358
f->state = EMPTY;
359-
erasePositive(future);
359+
erasePositive(channel);
360360
resume_Pos(stack, value);
361361
break;
362362
}
363363
}
364364
}
365365

366-
void c_future_wait(struct Pos future, Stack stack) {
367-
Future* f = (Future*)future.obj;
366+
void c_channel_wait(struct Pos channel, Stack stack) {
367+
Channel* f = (Channel*)channel.obj;
368368
switch (f->state) {
369369
case EMPTY: {
370370
f->state = WAITED;
371371
f->payload.stack = stack;
372-
erasePositive(future);
372+
erasePositive(channel);
373373
break;
374374
}
375-
case FILLED: {
375+
case SENDED: {
376376
struct Pos value = f->payload.value;
377377
f->state = EMPTY;
378-
erasePositive(future);
378+
erasePositive(channel);
379379
resume_Pos(stack, value);
380380
break;
381381
}
382382
case WAITED: {
383-
erasePositive(future);
383+
erasePositive(channel);
384384
eraseStack(stack);
385385
// TODO more graceful panic
386-
fprintf(stderr, "ERROR: Future already waited\n");
386+
fprintf(stderr, "ERROR: Channel already waited\n");
387387
exit(1);
388388
break;
389389
}

0 commit comments

Comments
 (0)