* This method accepts an infinite amount of future objects, closures or an array of future objects/closures
* in order to execute them in parallel. It will return back to you a future that will return back an array
* of results from every future that was executed. This way you can further attach processing and pipelining
* on the constructed array of values.
* results = all( f1, f2, f3 ).get()
* all( f1, f2, f3 ).then( (values) => logResults( values ) );
* @result A future that will return the results in an array
* This function can accept an array of items or a struct and apply a function
* to each of the item's in parallel. The `fn` argument receives the appropriate item
* and must return a result. Consider this a parallel map() operation
* allApply( items, ( item ) => item.getMemento() )
* // Struct: The result object is a struct of `key` and `value`
* allApply( data, ( item ) => item.key & item.value.toString() )
* @items An array to process
* @fn The function that will be applied to each of the array's items
* @executor The custom executor to use if passed, else the forkJoin Pool
* @return An array with the items processed
any function allApply( any items, required fn, executor ){
* This method accepts an infinite amount of future objects or closures and will execute them in parallel.
* However, instead of returning all of the results in an array like all(), this method will return
* the future that executes the fastest!
* // Let's say f2 executes the fastest!
* f2 = anyOf( f1, f2, f3 )
* @return The fastest executed future
* This method seeds a timeout into this future that can be used by the following operations:
* @timeout The timeout value to use, defaults to forever
* @timeUnit The time unit to use, available units are: days, hours, microseconds, milliseconds, minutes, nanoseconds, and seconds. The default is milliseconds
Future function withTimeout( numeric timeout = 0, string timeUnit = "milliseconds" )