Skip to content

Instantly share code, notes, and snippets.

@devyn
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devyn/1694f7fd5ddbce7726e1 to your computer and use it in GitHub Desktop.
Save devyn/1694f7fd5ddbce7726e1 to your computer and use it in GitHub Desktop.

Ordering guarantees in Paws

New call-pattern

Caller should own itself.

  1. Clone the subject.
  2. Request ownership for the subject clone over itself.
  3. Request ownership for the subject clone over caller.
  4. Stage subject clone with message. Can not realize until next step due to responsibility conflict.
  5. Drop ownership for caller over itself. This resolves the responsibility conflict, and now the subject clone can realize.

New call-pattern return protocol

  1. Request ownership for caller of itself. This will not succeed but will block further stagings.
  2. If returning a value, stage caller with that value here. It will block until you disown it. The other steps are still necessary even if not returning anything. However, you may allow Execution completion to automatically perform the final two steps.
  3. Disown caller. Caller is now free to execute, but there's no danger of interrupting us again until the next step.
  4. Disown self: this is the point at which others can now call you, so it may be desirable to put this in a subexpression.

infrastructure execution wait[]

Similar to stage[]. Implements call-pattern but appends the following steps:

  1. Request for the caller over itself again.
  2. Stage caller with the execution. This will block until the routine we called releases us.

Useful for calling non-returning routines, which I don't think is safe to do with stage[] alone. Could use a better name.

Example: implementing a call-pattern Execution

Given the following helper:

  • locals.push[], which adds a pair to locals
locals.push[] caller
  [infrastructure execution disown[] [] []];

infrastructure execution wait[]
  [infrastructure execution own[] [caller]] [caller];
infrastructure execution stage[]
  [caller] [];
infrastructure execution wait[]
  [infrastructure execution disown[] []] [caller];

locals.push[] argument.1
  [infrastructure execution disown[] [] []];

-- ... do something with `argument.1` and get `result` ...

infrastructure execution wait[]
  [infrastructure execution own[] [caller]] [caller];
infrastructure execution stage[]
  [caller] [result];

-- Everything else is disowned once the Execution completes.

Example:

Advantages

  • Paws-y. Only changes call-pattern semantics and adds one more routine that I'm not even completely sure is necessary if I can prove that there's no race condition.
  • Even allows non-returning routines to enforce ordering on the caller. (This was a big unsolved problem.)
  • Abstractable.

Disadvantages

  • Ugly. Not DRY. However, it is abstractable for sure.
  • Overuse of responsibility, which I'm not yet convinced is optimizable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment