leostera / reactor

🚀 Native Actors for Reason and OCaml
70 stars 5 forks source link

[Core] Refactor Process Abstraction #1

Closed leostera closed 6 years ago

leostera commented 6 years ago

This PR redefines the transitions between a process states to be typed more semantically, and makes consumption of a single-message synchronous.

State transitions

State transitions before were the return value of a process, and there wasn't a clean way of exiting a process other than with exit(self()) which is not very elegant. They are now defined as follow:

type behavior('s) =
  | Become('s)
  | Suspend(int, 's)
  | Terminate;
  1. A Process may become[0] another Process (albeit preserving it's identifier)
  2. A Process may suspend for some milliseconds before becoming (see 1)
  3. A Process may terminate.

The definition of the procesess' behaviors seems to be simplified considerably, and from the shitty benchmarks I'm making (profiling and the examples themselves) it seems to be considerable faster and use less memory.

I attribute this to the reduced amount of closures.

[0] become is standard lingo in the literature of Actors for a state-change-by-continuation-passing.

Message Consumption

Whereas before the env.recv/1 function took a continuation that will be evaluated with a message as soon as one is found sometime in the future, the new env.recv/0 immediately returns with the next message to be consumed, or with None if the mailbox is empty.

This means that code that used to look like

(env, state) => {
  env.recv( m => switch(m) {
     | SomeMessageThisProcessUnderstands(...x) => ...
     | _ => ...
  });
  Become(state);
}

Now looks like:

(env, state) => {
  switch(env.recv()) {
    | Some(m) => switch(m) {
      | SomeMessageThisProcessUnderstands(...x) => ...
      | _ => ...
    | None => ...
  }
  Become(state);
}

Which we can simplify with operators that work on Options much nicely :)

(env, state) => (env.recv() >>| handle_message <|> state) |> Become