#include "persifs.h"
#include "lockmanager.h"

#define DEBUG 0

lockManager::lockManager() 
{
}


lockManager::~lockManager()
{
}


void
lockManager::acquire(inumber lockId, callback<void>::ref cb)
{
#if DEBUG
  warn << "acquire lock " << lockId << "\n";
#endif
  lockRequest *req = New lockRequest(lockId, cb);

  lockStatus *status = locks[lockId];
  if (status == NULL) {
    status = New lockStatus;
    status->lockId = lockId;
    locks.insert(status);
    
    grantLock(status, req);
  } else {
    status->queue.insert_tail(req);
  }  
}


void
lockManager::release(inumber lockId)
{
#if DEBUG
  warn << "release lock " << lockId << "\n";
#endif
  lockStatus *status = locks[lockId];
  if (status == NULL) {
    fatal << "Attempting to release lock " << lockId
          << " which isn't held\n";
  }
  
  if (status->queue.first != NULL) {
    lockRequest *req = status->queue.first;
    status->queue.remove(req);
    grantLock(status, req);
  } else {
    locks.remove(status);
    delete status;
  }
}

void
lockManager::grantLock(lockStatus *lock, lockRequest *req)
{
#if DEBUG
  warn << "grant lock " << lock->lockId << "\n";
#endif
  if (lock->lockId != req->lockId) {
    fatal << "Attempting to grant a lock to a request with different id\n";
  }

  delaycb(0, req->cb);
  delete req;
}
