The Gallery is deprecated. No new Gallery components may be submitted, and modifying existing components is disabled. For more information please read the Gallery Deprecation blog post. This is a static snapshot of the Gallery for archive purposes.
See 42 more by this user. Created: 04/16/12
Last CDN Push: 12/12/13
Build Tag: gallery-2013.12.12-21-06
Project: YUI 3
License: YUI BSD
YUI Version: 3.5.1
Free for use.
Most people believe that Since JavaScript does not provide a multi-threaded shared memory environment, JavaScript is completely free from concurrency issues. This is true at a low level; JavaScript developers don't need to worry about race conditions between multiple processes or threads writing to the same memory location. At a higher level, asynchronous operations still allow for similar problems to occur.
Imagine a function that does the following:
1. Check the value of a variable.
2. If the value is undefined:
. 1. Make a request to a server.
. 2. Receive data.
. 3. Set the value of the variable.
3. Pass the variable to a callback function.
It seems common for web applications to lazy load data like this as needed. Now imagine that there are several separate modules within a web application which all require this data. It's possible for the first module to call this function, the function sees that the value is undefined, and sends a request to a server. Then before the request returns, the second module calls this function, the function sees that the value is undefined and sends a request to a server. Then before both of those requests return, the third module calls this function, the function sees that the value is undefined and sends a request to a server. In this case, three requests are made to a server for the same data.
It would be far better if the second and third calls to the function just waited for the first request to complete. Y.Mutex makes it easier to accomplish this functionality.
Y.Mutex provides a concept of locking a resource. Once an exclusive resource lock is obtained, other parts of an application which attempt to access the same resource, will have to wait until that resource is unlocked.
The function above could be rewritten as follows:
1. Obtain an exclusive lock for a variable.
2. Check the value of the variable.
3. If the value is undefined:
. 1. Make a request to a server.
. 2. Receive data.
. 3. Set the value of the variable.
4. Unlock the variable.
5. Pass the variable to a callback function.
This way, second or third or more calls to the function, before the first request is complete, will always wait for the request to complete instead of sending multiple unnecessary requests.
Just like locking in multi threaded applications, there are disadvantages and dangers to locking. There is a small amount of overhead added to every resource access, even when the chances for concurrency issues are very small. Once a lock is obtained, it must be unlocked; so error handling and time outs are important to ensure that the entire application doesn't break when something goes wrong. It is possible to cause a deadlock when locking multiple resources at once.
One advantage Y.Mutex has in JavaScript over other multi threaded applications, the locks are asynchronous. The application is not blocked while waiting to acquire a lock. Even if a deadlock occurs, other parts of the application are not affected. Y.Mutex also provides multiple ways to cancel a particular lock, so there are extra possibilities to recover from locking errors.
Y.Mutex offers exclusive locks, shared locks, and upgradable locks. When a resource is locked by an exclusive lock, Y.Mutex guarantees that no other locks will be granted for the resource until the resource is unlocked. When a resource is locked by a shared lock, Y.Mutex allows the resource to be locked by an unlimited number of other shared locks at the same time and/or one single upgradable lock. When a resource is locked by multiple shared locks, an exclusive lock can not be obtained until all of the shared locks have been unlocked. An upgradable lock can be upgraded to act as an exclusive lock. Shared locks are generally used when just reading values. Exclusive locks are generally used when writing values.
Y.Mutex provides a way to deal with asynchronous concurrency issues, but it does not prevent them. If code from part of an application uses Y.Mutex to lock a resource, there is nothing stopping code from another part of the application from ignoring the lock and accessing the resource directly. Y.Mutex does not handle real multi threaded or multi process concurrency issues.
Resources are locked by name. Y.Mutex has three public static methods.
To obtain an exclusive lock:
Y.Mutex.exclusive(resourceName, callbackFunction, timeout);
To obtain a shared lock:
Y.Mutex.shared(resourceName, callbackFunction, timeout);
To obtain an upgradable lock:
Y.Mutex.upgradable(resourceName, callbackFunction, timeout);
resourceName is the string name of the resource to lock.
callbackFunction is the function that is called when the lock is obtained. It is guaranteed not to be called synchronously. It is guaranteed not to be called more than once. It is not guaranteed to ever be called. The callbackFunction is passed the unlock function as its first argument which must be called in order to release the lock. For upgradable locks only, the second argument is the exclusive function which may be called to switch the upgradable lock to exclusive mode. The exclusive function accepts a callback function as its only argument. This callback function gets called once exclusivity is achieved. It is guaranteed not to be called synchronously. It is guaranteed not to be called more than once. It is not guaranteed ever to be called. The callback function is passed one argument, the shared function which may be called to switch the upgradable lock back to shared mode. The shared function accepts a callback function as its only argument. This callback function gets called once exclusivity is revoked. It is guaranteed not to be called synchronously. It is guaranteed not to be called more than once. It is not guaranteed ever to be called. The callback function is passed one argument, the exclusive function which may be called to switch the upgradable lock to exclusive mode.
timeout is the optional approximate time in milliseconds to wait after the callbackFunction has been called. Once the timeout has expired, if the callback function hasn't yet called the unlock function, the lock will be automatically released. This does not halt, stop, or prevent anything that the callbackFunction might still be doing asynchronously; it just releases the lock. Using timeout is one way to reduce the possibility of deadlocks, but it comes with the risk of allowing concurrent access to the resource.
Both Y.Mutex.exclusive, Y.Mutex.shared, and Y.Mutex.upgradable return an object with a cancel method. When the cancel method is called, if the callback function hasn't yet called the unlock function, the lock will be automatically released. This does not halt, stop, or prevent anything that the callbackFunction might still be doing asynchronously; it just releases the lock. Using the cancel method is one way to reduce the possibility of deadlocks, but it comes with the risk of allowing concurrent access to the resource.
<script src="http://yui.yahooapis.com/3.5.1/build/yui/yui-min.js"></script>
YUI({
//Last Gallery Build of this module
gallery: 'gallery-2013.12.12-21-06'
}).use('gallery-mutex', function(Y) {
var a = 0,
getA = function (callbackFunction) {
Y.Mutex.exclusive('a', function (unlock) {
if (a) {
unlock();
callbackFunction(a);
} else {
Y.io('http://my.server.com/get/a', {
on: {
complete: function (transactionId, response) {
a = response.responseText;
unlock();
callbackFunction(a);
}
}
});
}
});
};
getA(function (a) {
// Do something with a
});
getA(function (a) {
// Do something else with a
});
});
All code on this site is licensed under the BSD License unless stated otherwise.