Advertisement
Guest User

Untitled

a guest
Oct 19th, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.47 KB | None | 0 0
  1. const std = @import("std");
  2.  
  3. /// stores some state for each coroutine
  4. /// as well as a pointer to the frame to be resumed
  5. const CoroutineState = struct {
  6. pub const Self = @This();
  7.  
  8. frame: anyframe = undefined,
  9. quit: bool = false,
  10. active: bool = false,
  11.  
  12. /// must be called from within the coroutine
  13. /// as soon as the coroutine will exit.
  14. /// this is best done by using `defer coro.exit();`.
  15. pub fn exit(self: *Self) void {
  16. self.active = false;
  17. }
  18.  
  19. /// yields the coroutine.
  20. /// will return an error if the coroutine has been quit.
  21. fn yield(coro: *Self) !void {
  22. suspend {
  23. coro.frame = @frame();
  24. }
  25. if (coro.quit)
  26. return error.Cancelled;
  27. }
  28. };
  29.  
  30. var coroutines = [_]CoroutineState{CoroutineState{}} ** 3;
  31.  
  32. /// our coroutine
  33. fn loop(coro: *CoroutineState, prefix: []const u8, limit: i32) !void {
  34. defer coro.exit(); // must be called to recognize that the coroutine was stopped
  35.  
  36. std.debug.warn("{}: startup\n", prefix);
  37. defer std.debug.warn("{}: shutdown\n", prefix);
  38.  
  39. var repetition: i32 = 0;
  40. while (repetition < limit) : (repetition += 1) {
  41. std.debug.warn("{}: loop {}\n", prefix, repetition);
  42. try coro.yield(); // yield may throw error.Cancelled
  43. }
  44. }
  45.  
  46. /// starts a new coroutine with the given parameters
  47. fn start_new(prefix: []const u8, limit: i32) !@Frame(loop) {
  48. for (coroutines) |*coro| {
  49. if (coro.active)
  50. continue;
  51. coro.active = true;
  52. coro.quit = false;
  53. coro.frame = undefined;
  54. return async loop(coro, prefix, limit);
  55. }
  56. return error.OutOfMemory;
  57. }
  58.  
  59. pub fn main() !void {
  60. // this uses result location semantics to
  61. // store our coroutine frames in the main
  62. // function. in a proper implementation,
  63. // it should use an allocator
  64. _ = try start_new("o", 5);
  65. _ = try start_new("x", 10);
  66. _ = try start_new("~", 20);
  67.  
  68. // schedule our coroutines here 15 times
  69. var rep: u32 = 0;
  70. while (rep < 15) : (rep += 1) {
  71. var any_alive = false;
  72. for (coroutines) |coro| {
  73. // resume all alive coroutines
  74. if (!coro.active)
  75. continue;
  76. any_alive = true;
  77. resume coro.frame;
  78. }
  79. if (!any_alive)
  80. break;
  81. }
  82.  
  83. // kill all coroutines that are still alive
  84. for (coroutines) |*coro, index| {
  85. if (coro.active) {
  86. coro.quit = true;
  87. resume coro.frame;
  88. }
  89. }
  90. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement