Request Objects

When an entity makes a request to the simulation – such as set a timer, use a facility, etc – the simulator returns backs a Request object. The entity can use this Request object to further modify the original request.

The Request object is returned when an entity makes any of the following requests:

The Request object can then be used to modify the request in the following ways:

  • done(): Assign functions that must be called when the request is satisfied.
  • waitUntil(): Set a timeout value to the request. If the request is not satisfied within the timeout value, it will be terminated and the entity will be notified.
  • unlessEvent(): Put the request in the wait queue of one or more Events. If any one of those events is fired, the request will be terminated and the entity will be notified.
  • setData(): Assign some user data for this request, which will be returned back when the simulator notifies the entity about the request.
  • cancel(): Cancel the request.

Except for cancel(), all other functions return the Request object back, therefore, these functions can be chained together. For example:

// Example of chained function calls

this.putBuffer(buffer, 10)
.done(fnWhenSatisfied)
.done(fnAlsoWhenSatisfied)
.waitUntil(10, fnCouldNotAllocIn10Sec)
.unlessEvent(event1, fnEvent1Happened)
.unlessEvent(event2, fnEvent2Happened)
.setData('give me this data when ANY callback function is called');

The following table summarizes the various outcomes of a request and which callback functions are called in each case:

Outcome of Request callback in done() callback in waitUntil() callback in unlessEvent()
Request is satisfied Yes No No
Timeout occurs No Yes No
Event is fired No No Yes
cancel() called No No No

API Reference

class Sim.Request()

Note

The Request constructor should be considered as a private API. Application code should not explicitly create objects of this class.

Sim.Request.done(callback[, context[, argument]])

callback is a function (named or anonymous) that must be called when the request is satisfied.

context is the object in whose context the function will be called. The behavior is therefore equivalent to: callback.call(context). If context argument is not provided or is set to a value that evaluates to false, it is assumed to be the calling entity object.

argument are the optional arguments that are passed to the callback function. If argument is an array then the simulator will execute callback.apply(context, argument), otherwise the simulator will execute callback.call(context, argument).

Note 1: This function can be called multiple times for the same request object, in which case all the callback functions will be called. The simulator guarantees that the the ordering of callback functions will be same as the order in which they were added.

Note 2: If this function is not applied for a request object, then the simulator will still schedule this request and handle it appropriately. Other callback functions defined in waitUntil() or unlessEvent() may still be called. This is useful when the application is interested in error conditions only, for example:

// done() function is not applied to the request object.
// The simulator will schedule and process this request appropriately,
// and may call the other callback functions.
this.putBuffer(buffer, 10)
.unlessEvent(event, handleEvent)
.waitUntil(event, handleTimeout);

Note 3: Even if the request is immediately satisfied (for example, buffer has enough free space for the put request), the callback function will still be called after the function scope that made this request has finished. That is:

start: function() {
    // Adding 0 units.. should always succeed immediately
    this.putBuffer(buffer, 0).done(function () {
        document.write("I will be printed as second line.");
        });
    document.write("I will be printed as first line.");
}
Sim.Request.waitUntil(duration, callback[, context[, argument]])

Set a timeout value to the request. If the request is not satisfied within the duration time interval, it will be terminated and the callback function will be called.

context is the object in whose context the function will be called. The behavior is therefore equivalent to: callback.call(context). If context argument is not provided or is set to value that evaluates to false, it is assumed to be the calling entity object.

argument are the optional arguments that are passed to the callback function. If argument is an array then the simulator will execute callback.apply(context, argument), otherwise the simulator will execute callback.call(context, argument).

As noted in the table above, if the timeout occurs then no other callback function (for example, in done() or unlessEvent()) will be called.

Note: The API does not prevent calling this function multiple times, however, note that only one callback function (the one with smallest timeout value) is effectively useful.

Sim.Request.unlessEvent(event, callback[, context[, argument]])

event is either:

  • an object of Event() instance type, or
  • an array of objects, each an instance of Event().

Puts the request in the wait queue of one or more events. If any of those events are fired, the request will be terminated and the callback function will be called.

context is the object in whose context the function will be called. The behavior is therefore equivalent to: callback.call(context). If context argument is not provided or is set to value that evaluates to false, it is assumed to be the calling entity object.

argument are the optional arguments that are passed to the callback function. If argument is an array then the simulator will execute callback.apply(context, argument), otherwise the simulator will execute callback.call(context, argument).

As noted in the table above, if the timeout occurs then no other callback function (for example, in done() or waitUntil()) be called.

Note: This function can be called multiple times for the same request object. Note that if one event appears in more than one waitUntil() function, even then only one callback functions will be called. The simulator will non-deterministically select which callback function to call. The following table summarizes the semantics of the callback behavior of this function. Assume ev1 and ev2 are two events, and request is the Request object.

Code ev1 fired ev2 fired
request.unlessEvent(ev1, fn1).unlessEvent(ev2, fn2) fn1 called fn2 called
request.unlessEvent([ev1, ev2], fn1) fn1 called fn1 called
request.unlessEvent(ev1, fn1).unlessEvent(ev1, fn2) one of f1 or fn2 called  
Sim.Request.setData(data)

data can be any data type (primitive type, arrays, objects etc) which will be returned back when the simulator notifies the entity about the request.

From within the callback function, this data can be accessed through the this.callbackData attribute. This attribute is defined only during the scope of the callback function, and only during the time when the callback function is executing.

This function can be called multiple times for the same request object, but each new invocation will overwrite the data from previous calls.

The data, once set, will be returned to all callback function (if they are called).

For example:

var Entity = {
    start: function () {
        this.putBuffer(buffer, 10)
        .done(this.fn1)
        .unlessEvent(e, this.fn2)
        .setData('my data');

        // this.userData is undefined outside the callback functions
        assert(this.callbackData === undefined);
    },
    fn1: function () {
        assert(this.callbackData === 'my data');
    },
    fn2: function () {
        // this.userData is visible in all callback functions
        assert(this.callbackData === 'my data');
    }
};
Sim.Request.cancel()

Cancel a request. After this call, no callback function will be called.

Note

Special case with facilities.

In case of facilities with FIFO queuing discipline, the requesting entities go through two stages: (1) wait for the facility to become free (this may be zero duration if the facility is already free), and (2) use the facility for specified duration. The waitUntil(), unlessEvent() and cancel() functions are applicable in the first stage only. In order words, if an entity has started using the facility, then it cannot be dislodged and these function calls will have no effect.

In case of facilities with LIFO and Processor Sharing disciplines, the requesting entities obtain an immediate access to the facility resource. Therefore, waitUntil(), unlessEvent() and cancel() functions will have no effect for these facilities.

Callback Functions

Request class has three functions that accept callback functions: done(), waitUntil() and unlessEvent(). Before calling the callback functions, the simulator may assign one or more of these attributes in the context object:

  • this.callbackSource. The object for which this request was made.
    • for setTimer(), this.callbackSource is equal to undefined.
    • for useFacility(fac), this.callbackSource is equal to fac.
    • for putBuffer(buf), this.callbackSource is equal to buf.
    • for getBuffer(buf), this.callbackSource is equal to buf.
    • for putStore(store), this.callbackSource is equal to store.
    • for getStore(store), this.callbackSource is equal to store.
    • for waitEvent(event), this.callbackSource is equal to event.
    • for queueEvent(event), this.callbackSource is equal to event.
  • this.callbackMessage. Provides additional information. Currently, this attribute is set in following cases only:
    • If the request had a unlessEvent() clause and the corresponding callback function is called. This attribute points to the event that led to this callback function.
    • For useFacility(fac), the callback in done() reports the server id that was allocated to this request.
    • For getStore(store), the callback in done() points to the object that is returned by the store.
  • this.callbackData. User defined data through setData().

Table Of Contents

Previous topic

Simulator and Entity

Next topic

Resources: Facilities, Buffers and Stores