/// An async semaphore with up to `cap` locks held at once.
/// An async semaphore with up to `cap` locks held at once.
///
///
@ -61,6 +60,16 @@ function Semaphore(cap)
awaitnext.acquire();
awaitnext.acquire();
};
};
/// Attempt to acquire the semaphore lock if there is one available.
///
/// # Returns
/// `true` if the lock was acquired, `false` if the lock must be waited on to be acquired.
this.try_acquire_raw=()=>{
if(self.length<self.capacity){
self.length+=1;returntrue;
}returnfalse;
};
this.release_raw=()=>{
this.release_raw=()=>{
next.release();
next.release();
};
};
@ -68,19 +77,73 @@ function Semaphore(cap)
/// Acquire a semaphore lock (if one is not available, wait until one is) and then run `func()` with the lock held, afterwards, release the lock and return the result of `func()`.
/// Acquire a semaphore lock (if one is not available, wait until one is) and then run `func()` with the lock held, afterwards, release the lock and return the result of `func()`.
/// If `func` is an async function, it is awaited and the lock is released after it has resolved (or rejected), and the result of this function is the result of that promise.
/// If `func` is an async function, it is awaited and the lock is released after it has resolved (or rejected), and the result of this function is the result of that promise.
this.using=async(func)=>{
this.using=async(func)=>{
//if(!func || (typeof obj !== "function" && !isPromise(func))) throw `Parameter '{func}' is not a function or Promise.`;
//if(!func || (typeof obj !== "function" && !is_promise(func))) throw `Parameter '{func}' is not a function or Promise.`;
awaitself.acquire_raw();
awaitself.acquire_raw();
try{
try{
constrv=func();
constrv=func();
if(isPromise(rv))returnawaitrv;
if(is_promise(rv))returnawaitrv;
elsereturnrv;
elsereturnrv;
}finally{
}finally{
self.release_raw();
self.release_raw();
}
}
};
};
/// Attempt to acquire a semaphore lock and execute `func()` with that lock held. If there is no available lock, immediately return and do not attempt to run `func()`.
///
/// # Async `func()`
/// If `func` is an async function, the return value of this function will be an awaitable promise that will release the lock upon awaiting (resolved or rejected), and yield the value of the awaited promise.
///
/// # Returns
/// You can use the second parameter to the function, the object `opt`, to choose how success/failure is represented in the returned value from the function call/returned promise (in the case of `func()` returning a promise (see above))
///
/// ## On successfully acquireing the lock:
/// * If `opt.wrap === true`: An object in the form of `{success: true, value: <returned value>}`. If `opt.keep_func === "always"`, the object will include the field `"func": func` as well. (See below)
/// * Otherwise, just the returned value itself. (*default*)
///
/// ## On failing to acquire the lock:
/// * If `opt.wrap === true`: An object in the form of `{success: false, value: opt.or, func: <see below>}`
/// * Otherwise, just `opt.or`. (*default*)
///
/// ### Notes
/// * If `opt` has no field called `or`, `undefined` is used instead.
/// * If `opt` has a field called `keep_func` and that field is `=== true` or `=== "always"`, *and* `opt.wrap === true`: On a failure to acquire the lock, the wrapped object will be in the form `{ value: (opt.or || undefined), success: false, "func": func }`.