The deferred event concentrator is used to collect the results of multiple deferred event callbacks and forward them to a single deferred event callback chain. A typical example of setting up a deferred event concentrator to do this is shown in Listing 7.4. The full implementation of this example is present in the deferred examples package as DeferredConcentratorExample.
In the example, a deferred event concentrator is created using the reactor's factory method. A number of threadables are then created which are used to execute long running tasks - in the case of the example these are prime factorisations of arbitrary integer values. The deferred event objects returned on starting the threadable tasks are then added as inputs to the deferred event concentrator, which automatically terminates their callback chains.
The final stage is to attach the callback handlers to the output of the deferred event concentrator. A handle on the output deferred event object is obtained by calling the getOutputDeferred method on the deferred event concentrator. When this method is first called on a given concentrator object, the concentrator is `locked' so that further inputs cannot be added. Once locked, any attempts to call addInputDeferred on the concentrator object will result in an exception of type DeferredTerminationException. Callback handlers can be attached to the output deferred event object in the normal fashion, with the output callback chain being ready for triggering once it has been correctly terminated.
In the event that all input deferred events complete successfully (ie, issue callbacks rather than errbacks), the callback parameter data for each deferred event is added to an ordered list. Once all deferred event inputs have issued their callbacks, this ordered list is then passed as the parameter to the output callback chain. In the example, this list contains string representations of the calculated prime factors. Listing 7.5 shows a callback handler which may be used to print out these results to the console.
A significant feature of the results list passed by the concentrator's output callback is that its ordering is consistent with the order in which input deferred events were added to the concentrator. This means that the result passed back by the first deferred input event to be added to the concentrator will be placed at the start of the list, with the results from other deferred input events being added in order. In the example, this means that the printed result can combine ordered data associated with the input deferred events (the nums array) with the ordered data placed in the results list by the concentrator (the data list).
When one of the deferred event inputs to a concentrator object generates an errback condition, this will be immediately propagated to the concentrator's output. Since the output deferred event object can only handle a single errback condition, only the first errback to occur will be propagated in this manner. All successful callback inputs and subsequent errback inputs will be silently discarded.