• Jump To … +
    browser.coffee cake.coffee coffee-script.coffee command.coffee grammar.coffee helpers.coffee iced.coffee icedlib.coffee index.coffee lexer.coffee nodes.coffee optparse.coffee repl.coffee rewriter.coffee scope.litcoffee sourcemap.litcoffee
  • icedlib.coffee

  • ¶
    iced_internals = require('./iced')
    exports.iced = iced = iced_internals.runtime
  • ¶

    icedlib

    This class contains non-essential but convenient runtime libraries for iced programs

    The timeout connector, which allows us to compose timeouts with existing event-based calls

    _timeout = (cb, t, res, tmp) ->
        rv = new iced.Rendezvous
        tmp[0] = rv.id(true).defer(arr...)
        setTimeout rv.id(false).defer(), t
        await rv.wait defer which
        res[0] = which if res
        cb.apply(null, arr)
    
    exports.timeout = (cb, t, res) ->    
      tmp = []
      _timeout cb, t, res, tmp
      tmp[0]
  • ¶

    The 'and' connector, that allows you to check only once that all operations with a parallel await worked...

    _iand = (cb, res, tmp) ->
      await
        tmp[0] = defer ok
      res[0] = false unless ok
      cb()
  • ¶

    this function takes as input two values: a callback, and a place to store a result. It returns a new callback.

    exports.iand = (cb, res) ->
      tmp = []
      _iand cb, res, tmp
      tmp[0]
  • ¶

    The 'or' connector, that allows you to check only once that one of several operations in a parallel await worked

    _ior = (cb, res, tmp) ->
      await
        tmp[0] = defer ok
      res[0] = true if ok
      cb()
    
    exports.ior = (cb, res) ->
      tmp = []
      _ior cb, res, tmp
      tmp[0]
  • ¶

    #

    Pipeliner -- a class for firing a follow of network calls in a pipelined fashion, so that only so many of them are outstanding at once.

    exports.Pipeliner = class Pipeliner
    
      constructor : (window, delay) ->
        @window = window || 1
        @delay = delay || 0
        @queue = []
        @n_out = 0
        @cb = null
  • ¶

    This is a hack to work with the desugaring of 'defer' output by the coffee compiler. Same as in rendezvous

        @[iced_internals.const.deferrals] = this
  • ¶

    Rebind "defer" to "_defer"; We can't do this directly since the compiler would pick it up

        @["defer"] = @_defer
  • ¶

    Call this to wait in a queue until there is room in the window

      waitInQueue : (cb) ->
  • ¶

    Wait until there is room in the window.

        while @n_out >= @window
          await (@cb = defer())
  • ¶

    Lanuch a computation, so mark that there's one more guy outstanding.

        @n_out++
  • ¶

    Delay if that was asked for...

        if @delay
          await setTimeout defer(), @delay
          
        cb()
  • ¶

    Helper for this._defer, seen below..

      __defer : (out, deferArgs) ->
  • ¶

    Make a callback that this.defer can return. This callback might have to fill in slots when its fulfilled, so that's why we need to wrap the output of defer() in an anonymous wrapper.

        await
          voidCb = defer()
          out[0] = (args...) ->
            deferArgs.assign_fn?.apply null, args
            voidCb()
  • ¶

    There is now one fewer outstanding computation.

        @n_out--
  • ¶

    If some is waiting in waitInQueue above, then now is the time to release him. Use "race-free" callback technique.

        if @cb
          tmp = @cb
          @cb = null
          tmp()
  • ¶

    This function, Pipeliner._defer, has to return a callback to its caller. It does this with the same trick above. The helper function _defer() does the heavy lifting, returning its callback to us as the first slot in tmp[0].

      _defer : (deferArgs) ->
        tmp = []
        @__defer tmp, deferArgs
        tmp[0]
  • ¶

    flush everything left in the pipe

      flush : (autocb) ->
        while @n_out
          await (@cb = defer())