Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cancel specific pending lock #64

Open
AndreMaz opened this issue Oct 5, 2022 · 5 comments
Open

Cancel specific pending lock #64

AndreMaz opened this issue Oct 5, 2022 · 5 comments

Comments

@AndreMaz
Copy link

AndreMaz commented Oct 5, 2022

Hi @DirtyHairy thank you for the great lib!

I wanted to ask you if there's a way to cancel() some specific pending locks of a mutex? In the docs it states

Pending locks can be cancelled by calling cancel() on the mutex. This will reject all pending locks with E_CANCELED:

However, in some situations I want to cancel only a specific lock while leaving others waiting for the lock to become available. I took a quick look at the source code but didn't find a way of achieving this. Can you please provide some pointers about how to make this possible?
I guess that the runExclusive() will have to return an ID that later can be used to cancel (e.g., cancel(<ID>)) the pending lock.

@DirtyHairy
Copy link
Owner

DirtyHairy commented Apr 14, 2023

Hi @AndreMaz !

Sorry for the late reply. Returning an ID would be the way to go, but this would mean that acquire and runExclusive would have to return two values, one being a promise, and one being the ID. This would mean that the result cannot be awaited directly, but it would have to be destructured, and the promise would have to be awaited.

Imo this makes those methods too quirky just to accomodate an edge case. The same effect can be easily achieved by the application by wrapping the promise returned by the library in another Promise and cancelling that.

@CMCDragonkai
Copy link

Imo this makes those methods too quirky just to accomodate an edge case. The same effect can be easily achieved by the application by wrapping the promise returned by the library in another Promise and cancelling that.

What do you mean by wrapping the promise returned by another library and cancelling that. How would this end up cancelling a specific pending lock?

For example if I race lock acqusition like await Promise.race([lock.acquire(), abortP]); then if abortP were to reject first, then lock.acquire() would still be pending, although it would be a dangling promise that can be garbage collected... would that lock.acquire() dangling promise end up eventually acquiring the lock and preventing blocking other acquirers?

@DirtyHairy
Copy link
Owner

What do you mean by wrapping the promise returned by another library and cancelling that. How would this end up cancelling a specific pending lock?

You're right, I must've been in a hurry when I wrote the reply above, and the response is a bit misleading. What I really meant is something like:

function cancellableAcquire(mutex: Mutex): [Promise<void>, () => void] {
  let rejectFn: undefined | (() => void);
  let cancelled = false;

  return [
    new Promise((resolve, reject) => {
      rejectFn = reject;
      mutex.acquire.then(release => cancelled ? release() : resolve(release), reject);
    }),
    () => {
      cancelled = true;
      rejectFn?.();
    }
  ]
}

@dmurvihill
Copy link
Contributor

Consider allowing cancel() to just accept the original Promise back directly and finding it with ===. It would require a linear scan of the entire queue (worst case), but that's probably fast enough for most use cases.

@DirtyHairy
Copy link
Owner

Yeah, that would work. Of course, the danger with promises is that it is easy to keep track of the original promise, but we could add all Promises to a WeakSet before returning them and throw an exception if cancel is called on a 'foreign' promise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants