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

Be able to supply string keys and have mutexes created and destroyed automatically #11

Open
tjenkinson opened this issue Apr 22, 2016 · 7 comments

Comments

@tjenkinson
Copy link
Contributor

So that you could do.

locks.lock("something", function() {
   locks.unlock("something");
});
// etc

Detecting when a mutex no longer has anything in its queue and can therefore be removed is actually quite complex, and the user has to maintain a map of all their mutexes to keys.

@tjenkinson
Copy link
Contributor Author

This is what I've done in my app. I use getMutex(key) whenever I retrieve a mutex for a particular key, and call unlockMutex(key) to unlock. I never call the unlock() method on the mutex object directly.

var mutexes = {};
function getMutex(key) {
    if (mutexes[key]) {
        return mutexes[key];
    }
    setTimeout(function() {
        // to handle if a mutex is retrieved but never locked (and therefore unlocked)
        cleanupMutex(key);
    }, 0);
    return mutexes[key] = locks.createMutex();
}

function unlockMutex(key) {
    mutexes[key].unlock();
    cleanupMutex(key);
}

function cleanupMutex(key) {
    if (!mutexes[key] || mutexes[key].isLocked) {
        // no longer exists or not in use
        return;
    }
    delete mutexes[key];
}

@ronkorving
Copy link
Collaborator

I'm thinking we could also support what C# does with locking: locking objects.
Say you want to have a mutex around:

var obj = new Whatever();

Imagine doing this (with a WeakMap instance completely doable):

var lock = Mutex.lock(obj);
Mutex.unlock(obj);

Would that be an interesting solution too? I'm a bit hesitant to create a key lookup map, but a WeakMap (unfortunately not useful for strings) would be a leak-safe way to provide functionality like this.

@tjenkinson
Copy link
Contributor Author

Hadn't heard of WeakMap's before they look pretty interesting. Will have to have a think but still not sure that would work for my use case though.

Here's an example:

function retrieveSomething(id) {

  return new Promise(function(resolve) {
      // if the thing is already being retrieved and cached, wait for the retrieval to complete, and then resolve with it
      if (!locks.tryLock(id)) {
         locks.lock(id, function() {
            locks.unlock(id);
            // resolve with the cached value
         });
      }
      else {
         // else start retrieving the thing, cache it
         locks.unlock(id);
         // resolve with the result
      }

  });
}

This means the work which is carried out to generate the "something" will only ever happen once at a time, with future calls resolving the promise that has just been done.

@ronkorving
Copy link
Collaborator

It would work for your use case if you didn't pass an ID to your function but an object:

var heldLocks = new WeakMap();

function retrieveSomething(obj) {
  var id = obj.id;
  var isLocked = heldLocks[obj] || false;

  return new Promise(function(resolve) {
      // if the thing is already being retrieved and cached, wait for the retrieval to complete, and then resolve with it
      if (!locks.tryLock()) {
         locks.lock(id, function() {
            heldLocks.set(obj, true);
            locks.unlock(id);
            heldLocks.delete(obj);
            // resolve with the cached value
         });
      }
      else {
         heldLocks.set(obj, true);
         // else start retrieving the thing, cache it
         locks.unlock(id);
         heldLocks.delete(obj);
         // resolve with the result
      }
  });
}

@tjenkinson
Copy link
Contributor Author

@ronkorving that would work but obj in my case would be a string. I think it might be possible to have a WeakMap which contains mappings between these strings and lock objects.

Then maybe this could go into the library itself so you could simply do locks.lock("some-key")?

So it would check and if the provided lock object is a string, put it in a weak map and then look up from there when needed to get the actual lock object.

@vaidik
Copy link

vaidik commented Mar 21, 2017

+1. It would be great if we can get this. I had to write my own implementation to get this to work.

@ronkorving
Copy link
Collaborator

@vaidik Using strings or object references in a weakmap?

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

3 participants