Skip to content

Commit

Permalink
Update readme with more examples.
Browse files Browse the repository at this point in the history
  • Loading branch information
jjrv committed May 10, 2016
1 parent c57c0fd commit c0737d6
Showing 1 changed file with 99 additions and 5 deletions.
104 changes: 99 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Then just call `queue.wrap(<function>)` instead of `<function>` to limit simulta

Simple Node.js example:

```typescript
```TypeScript
import * as Promise from 'bluebird';
import {TaskQueue} from 'cwait';

Expand All @@ -41,6 +41,96 @@ npm install
npm test
```

Recursion
---------

Recursive loops that run in parallel require special care.
Nested concurrency-limited calls (that are not tail-recursive) must be wrapped in `queue.unblock()`.

Here's a simple example that fails:

```JavaScript
var queue = new (require('cwait').TaskQueue)(Promise, 3);

var rec = queue.wrap(function(n) {
console.log(n);
return(n && Promise.resolve(rec(n - 1)));
});

rec(10);
```

It only prints numbers 10, 9 and 8.
More calls don't get scheduled because there are already 3 promises pending.
For example Node.js exits immediately afterwards because the program is not blocked waiting for any system calls.

Passing a promise to `queue.unblock(promise)` tells `queue` that
the current function will wait for `promise` to resolve before continuing.
One additional concurrent function is then allowed until the promise resolves.

Be careful not to call `queue.unblock()` more than once (concurrently) from inside a wrapped function!
Otherwise the queue may permit more simultaneous tasks than the intended limit.

Here is a corrected example:

```JavaScript
var queue = new (require('cwait').TaskQueue)(Promise, 3);

var rec = queue.wrap(function(n) {
console.log(n);
return(n && queue.unblock(Promise.resolve(rec(n - 1))));
});

rec(10);
```

Advanced example with recursion
-------------------------------

The following code recursively calculates the 10th Fibonacci number (55)
running 3 recursive steps in parallel, each with an artificial 10-millisecond delay.

At the end, it prints the result (55) and the number of concurrent calls (3).

```JavaScript
var queue = new (require('cwait').TaskQueue)(Promise, 3);

var maxRunning = 0;
var running = 0;
var delay = 10;

var fib = queue.wrap(function(n) {
// "Calculation" starts. Track maximum concurrent executions.
if(++running > maxRunning) maxRunning = running;

return(new Promise(function(resolve, reject) {
setTimeout(function() {
// "Calculation" ends.
--running;

// Each Fibonacci number is the sum of the previous two, except
// the first ones are 0, 1 (starting from the 0th number).
// Calculate them in parallel and unblock the queue until ready.

resolve(n < 2 ? n :
queue.unblock(Promise.all([
fib(n - 1),
fib(n - 2)
])).then(function(r) {
// Sum results from parallel recursion.
return(r[0] + r[1]);
})
);
}, delay);
}));
});

fib(10).then(function(x) {
console.log('Result: ' + x);
console.log('Concurrency: ' + maxRunning);
});
```

API
===
Docs generated using [`docts`](https://github.com/charto/docts)
Expand All @@ -64,17 +154,21 @@ Docs generated using [`docts`](https://github.com/charto/docts)
>
> <a name="api-TaskQueue"></a>
> ### Class [`TaskQueue`](#api-TaskQueue)
> Source code: [`<>`](http://github.com/charto/cwait/blob/bcc3b2b/src/TaskQueue.ts#L6-L60)
> Source code: [`<>`](http://github.com/charto/cwait/blob/c57c0fd/src/TaskQueue.ts#L6-L75)
>
> Methods:
> > **new( )** <sup>&rArr; <code>[TaskQueue](#api-TaskQueue)&lt;PromiseType&gt;</code></sup> [`<>`](http://github.com/charto/cwait/blob/bcc3b2b/src/TaskQueue.ts#L7-L11)
> > **new( )** <sup>&rArr; <code>[TaskQueue](#api-TaskQueue)&lt;PromiseType&gt;</code></sup> [`<>`](http://github.com/charto/cwait/blob/c57c0fd/src/TaskQueue.ts#L7-L11)
> > &emsp;&#x25aa; Promise <sup><code>[PromisyClass](#api-PromisyClass)&lt;PromiseType&gt;</code></sup>
> > &emsp;&#x25aa; concurrency <sup><code>number</code></sup>
> > **.add( )** <sup>&rArr; <code>PromiseType</code></sup> [`<>`](http://github.com/charto/cwait/blob/bcc3b2b/src/TaskQueue.ts#L16-L33)
> > **.add( )** <sup>&rArr; <code>PromiseType</code></sup> [`<>`](http://github.com/charto/cwait/blob/c57c0fd/src/TaskQueue.ts#L16-L33)
> > &emsp;<em>Add a new task to the queue.</em>
> > &emsp;<em>It will start when the number of other concurrent tasks is low enough.</em>
> > &emsp;&#x25aa; func <sup><code>() =&gt; PromiseType</code></sup>
> > **.wrap( )** <sup>&rArr; <code>(...args: any[]) =&gt; PromiseType</code></sup> [`<>`](http://github.com/charto/cwait/blob/bcc3b2b/src/TaskQueue.ts#L38-L40)
> > **.unblock( )** <sup>&rArr; <code>PromiseType</code></sup> [`<>`](http://github.com/charto/cwait/blob/c57c0fd/src/TaskQueue.ts#L38-L46)
> > &emsp;<em>Consider current function idle until promise resolves.</em>
> > &emsp;<em>Useful for making recursive calls.</em>
> > &emsp;&#x25aa; promise <sup><code>PromiseType</code></sup>
> > **.wrap( )** <sup>&rArr; <code>(...args: any[]) =&gt; PromiseType</code></sup> [`<>`](http://github.com/charto/cwait/blob/c57c0fd/src/TaskQueue.ts#L51-L53)
> > &emsp;<em>Wrap a function returning a promise, so that before running</em>
> > &emsp;<em>it waits until concurrent invocations are below this queue's limit.</em>
> > &emsp;&#x25aa; func <sup><code>(...args: any[]) =&gt; PromiseType</code></sup>
Expand Down

0 comments on commit c0737d6

Please sign in to comment.