Compare commits

..

10 Commits

Author SHA1 Message Date
Avril b7f3249180
Update README for a section on `Semaphore` (semaphore.js).
3 years ago
Avril 7b438a930f
Merge branch 'allow-await-async-timeout-func'
3 years ago
Avril 77926dd1f9
Semaphore: Added `try_acquire()`, `try_using()` (see docs). Added `bind_using(func)` to returned a bound function of `func` to `this.using`.
3 years ago
Avril b2070f1918
Semaphore: Better example function. Changed `Semaphore.Mutex()` -> `Semaphore.mutex()` to avoid class naming convention confusion.
3 years ago
Avril d54a5e8f51 Uhh, fixed semaphore. It works now.
3 years ago
Avril d151412576
WHY DOESN"T THIS FUKCINGA I STUPID THING WORK????? RESOLVE IS ***PROVEN*** TO ____NOT____ BE CALLED IN THE PROMISE CTOR SO WHY THE FUCK IS THAT PROMISE RESOLVING IMMEDIATELY!??!?!?!??!???!??!??!?!?!?!?
3 years ago
Avril bc64ae9232
semaphore attampt 1: failure
3 years ago
Avril ed32e1586b
Changed `exmaple()` to `console.log()` instead of `alert()`.
3 years ago
Avril 881be9a6e7
Fix syntax error
3 years ago
Avril 05daa18891
Update README
3 years ago

@ -8,12 +8,18 @@ There are two methods on the class `AsyncTimeout(func, time)`:
* `timeout()`: Creates an `await`able promise that will resolve to the value of `func()` when the timeout `time` is reached. * `timeout()`: Creates an `await`able promise that will resolve to the value of `func()` when the timeout `time` is reached.
* `interval()`: Creates a `for await`able async iterator that will resolve to the value of `func()` each `time` it is called. To cancel the interval, simply break from the loop or stop calling `.next()` on the returned async iterator. * `interval()`: Creates a `for await`able async iterator that will resolve to the value of `func()` each `time` it is called. To cancel the interval, simply break from the loop or stop calling `.next()` on the returned async iterator.
### Static methods
There are two helper functions in `AsyncTimeout`:
* `await_timeout(time)`: Returns a promise that resolves with no value after `time`.
* `await_interval(time)`: Returns an infinite async iterator that yields no value for every interval of `time`.
## Parameters ## Parameters
* `thing` - The function to call after the timeout/interval. The result of the promise (or the yield for `interval()`) is the result of this function call. If the funtion throws, then the rejection of the promise will be that error thrown. * `thing` - The function to call after the timeout/interval. The result of the promise (or the yield for `interval()`) is the result of this function call. If the funtion throws, then the rejection of the promise will be that error thrown.
If this is an async function, then it is awaited inside the returned/yielded promise, and its resolution becomes the resolved value for the returned/yielded promise; likewise, its rejection becomes the rejection for the returned/yielded promise.
* `interval` - The time to wait for the timeout or interval * `interval` - The time to wait for the timeout or interval
## Example usages ## Example usages
See `example()` in the file for detail. See `timeout_example()`, or `try_example()` in the file for detail.
### `setTimeout()` promisified ### `setTimeout()` promisified
`await (new AsyncTimeout(() => "value", 100)).timeout() /* === "value" */` is `setTimeout(()=> "value", 100)` promisified. `await (new AsyncTimeout(() => "value", 100)).timeout() /* === "value" */` is `setTimeout(()=> "value", 100)` promisified.
@ -24,4 +30,35 @@ See `example()` in the file for detail.
This is an infinite iterator. To cancel the interval, simply break out of the `for await` loop or otherwise stop using the iterator returned from `.interval()`. This is an infinite iterator. To cancel the interval, simply break out of the `for await` loop or otherwise stop using the iterator returned from `.interval()`.
# Semaphore - A simple async seamphore implementation for JavaScript
The class `Semaphore(cap)` inside `semaphore.js` is a robust async semaphore implementation.
Its locking permits are queued (meaning, multiple waiting *acquire*ing calls will resolve in the order they are called.)
See the file `semaphore.js` for more information on how it's used, and the function `sem_example(cap || 1)` in that file.
## Methods
Raw acquire/release of semaphore lock:
* `acquire_raw()`: An async function that resolves when a lock is available, acquiring that lock. You must `release_raw()` this lock after its use.
* `release_raw()`: A function that releases a semaphore lock, or passes it to a waiting *acquireing* call.
* `try_acquire_raw()`: Attempts to acquire a semaphore lock if one is available, and returns `true` if one was available and the lock was taken, `false` if there were no available locks and one was not taken. If this function returns `true`, you must pair it with a `release_raw()` call after the lock has been used.
Automatic semaphore lock acquisition functions:
* `using(func)`: An async function that acquires a lock, runs `func()` (and awaits it if it is an async function), and then releases the lock no matter if the function threw or not.
* `bind_using(func)`: A function that returns a function that when invoked, acts as `using(func)`. This can be used to bind functions to the semaphore to be executed later.
* `try_using(func, opt)`: A function that attempts to acquire a lock, runs `func()` if it can, releases the lock, then returns the value from the `func()` call if it succeeded. If a lock cannot be acquired, `opt` can be used to dictate what or how values are returned (see doc comment on `try_using` for more information on how to use this parameter, by default the return value on a failure to acquire a lock immediately is `false`.) If `func` is an async function, a promise is returned that when awaited, will release the lock and return the resolution of the promise (or throw the exception of the promise's rejection.)
### Static methods
* `Semaphore.mutex()`: Returns a new mutex (a `Semaphore` instance with a capacity of `1`.)
## Parameters
* `cap`: An integer larger than 0 which dictates how many locks can be acquired at one time before *acquire*ing methods need to wait for one to be available.
## Fields
These fields should almost never be modified directly.
* `length`: The number of locks currently held.
* `capacity`: The max number of concurrent locks allowed to be held before new *acquire*ing methods must wait for a lock to be released.

@ -131,7 +131,9 @@ function Semaphore(cap)
// `rv` is a promise, wrap it's awaiting inside a new promise that release the lock regardless of if awaiting `rv` throws. // `rv` is a promise, wrap it's awaiting inside a new promise that release the lock regardless of if awaiting `rv` throws.
try { try {
return wrap_success(await rv, true); return wrap_success(await rv, true);
} finally { self.release_raw(); } } /*catch(e) { // Prevent an exception from crashing, use it to resolve the promise instead. //XXX: This might not be needed, since we are returning this promise, it should be awaited which will prevent the exception from bubbling up.
return wrap_success(opt.or, false);
}*/ finally { self.release_raw(); }
})(); })();
else { else {
// `rv` is not a promise, we can release the lock and return the value // `rv` is not a promise, we can release the lock and return the value

Loading…
Cancel
Save