var nLocks=0;function LockCounter(){this.nTiles=0;if(!LockCounter.NextID)LockCounter.NextID=0;this.id=++LockCounter.NextID;this.increase=function(){nLocks ++;}
this.decrease=function(){if(nLocks>0)nLocks --;if(nLocks<0){}
}
this.getLocks=function(){return nLocks;}
this.initLocks=function(nMaxLocks){if(nLocks==0)nLocks=this.nTiles;}
this.syncIncrease=function(){new Mutex(this,"increase");}
this.syncDecrease=function(){new Mutex(this,"decrease");}
this.syncGetLocks=function(){new Mutex(this,"getLocks");}
this.syncInitLocks=function(){new Mutex(this,"initLocks");}
}
function Map(){this.map=new Object();this.add=function(k,o){this.map[k]=o;}
this.remove=function(k){delete this.map[k];}
this.get=function(k){return k==null ? null:this.map[k];}
this.first=function(){return this.get(this.nextKey());}
this.next=function(k){return this.get(this.nextKey(k));}
this.nextKey=function(k){for(i in this.map){if(!k)return i;if(k==i)k=null;}
return null;}
}
function Mutex(cmdObject,methodName){if(!Mutex.Wait)Mutex.Wait=new Map();Mutex.SLICE=function(cmdID,startID){Mutex.Wait.get(cmdID).attempt(Mutex.Wait.get(startID));}
this.attempt=function(start){for(var j=start;j;j=Mutex.Wait.next(j.c.id)){if(j.enter||(j.number&&(j.number<this.number||(j.number==this.number&&j.c.id<this.c.id)))){return setTimeout("Mutex.SLICE("+this.c.id+","+j.c.id+")",10);}
}
this.c[this.methodID]();this.number=0;Mutex.Wait.remove(this.c.id);}
this.c=cmdObject;this.methodID=methodName;Mutex.Wait.add(this.c.id,this);this.enter=true;this.number=(new Date()).getTime();this.enter=false;this.attempt(Mutex.Wait.first());}
