/*
   SimpleLock.java
   
   Description:
      Simple lock class. The lock is an exclusive lock and
      supports recursive locking.

   Author:     Moggen
   Homepage:   http://www.moggen.org/
   License:    Public Domain, use as you like

   Log:
      010416   First version
*/

import java.util.ArrayList;

public class SimpleLock {

   // Status codes
   public static final int OK=0;
   public static final int NOT_OWNER=1;
   
   private ArrayList requestQueue;
   private Thread owner;
   private int level;

   public SimpleLock() {
      requestQueue=new ArrayList();
      owner=null;
      level=0;
   }
   
   // requestLock: Aquires the lock

   public synchronized int requestLock() {
      Thread thread=Thread.currentThread();

      if(owner==null){
         // The lock is not held by anyone
         owner=thread;
         level=1;
         return OK;
      }
      
      if(owner==thread){
         // We already got the lock, increment level
         level++;
         return OK;
      }
      
      // Some thread else got the lock, we must queue
      requestQueue.add(thread);

      Thread thr;
      
      // Loop forever. Hopefully we get a lock and return before eternity
      while(true){
         // Wait until something happens. This will release the monitor on
         // the lock instance and let other threads call methods.
         try{
            this.wait();
         } catch(InterruptedException e) {} // Todo: better handling here
          // Thread woke up, the monitor is reclaimed and we are synchronized
         // again
         
         // Is the lock free?
         if(owner==null){
            // Yes         
            thr=(Thread)requestQueue.get(0);
            // Is it our turn yet?
            if(thr==thread){
               // Yes
               // Remove from queue, set as owner
               requestQueue.remove(0);
               owner=thread;
               level=1;
               return OK;
            } else {
               // No, not our turn yet, wait again
            }
         } else {
            // The lock was not free. There was another thread first in the
            // queue and it got woken up before us and have got the lock
            // already. We must wait again
         }
      }           
      // The while doesn't end, so we never reach this line
      // javac complains if we try to return anyhing here
   }      

   // releaseLock: Releases the lock
  
   public synchronized int releaseLock() {
      Thread thread=Thread.currentThread();

      if(owner!=thread){
         // We don't own the lock, return error!
         return NOT_OWNER;
      }
      
      level--;
      if(level>0){
         // Still more requests than frees
         return OK;
      }

      // The lock is to be freed
      owner=null;
      if(!requestQueue.isEmpty()){
         // Wake up the others if there are any left waiting
         this.notifyAll();
      }

      return OK;
   }

   // releaseAll: Releases all levels of the lock. Usable in clean-up
   // code to release locks totally no matter the recursive level or
   // if the lock is aquired at all

   public synchronized void releaseAll() {
      Thread thread=Thread.currentThread();

      if(owner!=thread){
         // We don't own the lock
         return;
      }
      
      level=0;
      owner=null;
      if(!requestQueue.isEmpty()){
         // Wake up the others if there are any left waiting
         this.notifyAll();
      }
   }
}
