@@ -295,6 +295,90 @@ void c_yield(Stack stack) {
295
295
c_timer_start (0 , stack );
296
296
}
297
297
298
+ // Futures
299
+ // -------
300
+
301
+ typedef enum { EMPTY , FILLED , WAITED } future_state_t ;
302
+
303
+ typedef struct {
304
+ uint64_t rc ;
305
+ void * eraser ;
306
+ future_state_t state ;
307
+ union {
308
+ struct Pos value ;
309
+ Stack stack ;
310
+ } payload ;
311
+ } Future ;
312
+
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 ;
317
+ switch (state ) {
318
+ case EMPTY :
319
+ break ;
320
+ case FILLED :
321
+ erasePositive (future -> payload .value );
322
+ break ;
323
+ case WAITED :
324
+ eraseStack (future -> payload .stack );
325
+ break ;
326
+ }
327
+ }
328
+
329
+ struct Pos c_future_make () {
330
+ Future * future = (Future * )malloc (sizeof (Future ));
331
+
332
+ future -> rc = 0 ;
333
+ future -> eraser = c_future_erase ;
334
+ future -> state = EMPTY ;
335
+
336
+ return (struct Pos ) { .tag = 0 , .obj = future , };
337
+ }
338
+
339
+ void c_future_fill (struct Pos future , struct Pos value ) {
340
+ Future * f = (Future * )future .obj ;
341
+ switch (f -> state ) {
342
+ case EMPTY :
343
+ f -> state = FILLED ;
344
+ f -> payload .value = value ;
345
+ break ;
346
+ case FILLED :
347
+ erasePositive (future );
348
+ erasePositive (value );
349
+ // TODO more graceful panic
350
+ fprintf (stderr , "ERROR: Future already filled\n" );
351
+ exit (1 );
352
+ break ;
353
+ case WAITED :
354
+ Stack stack = f -> payload .stack ;
355
+ free (f );
356
+ resume_Pos (stack , value );
357
+ break ;
358
+ }
359
+ }
360
+
361
+ void c_future_wait (struct Pos future , Stack stack ) {
362
+ Future * f = (Future * )future .obj ;
363
+ switch (f -> state ) {
364
+ case EMPTY :
365
+ f -> state = WAITED ;
366
+ f -> payload .stack = stack ;
367
+ break ;
368
+ case FILLED :
369
+ struct Pos value = f -> payload .value ;
370
+ free (f );
371
+ resume_Pos (stack , value );
372
+ break ;
373
+ case WAITED :
374
+ erasePositive (future );
375
+ eraseStack (stack );
376
+ // TODO more graceful panic
377
+ fprintf (stderr , "ERROR: Future already waited\n" );
378
+ exit (1 );
379
+ break ;
380
+ }
381
+ }
298
382
299
383
// Promises
300
384
// --------
0 commit comments