blob: 846296067b9e9d48239a71dd01f5584fec4a2b33 [file] [log] [blame]
//===------------- VMObject.cpp - VM object definition --------------------===//
//
// N3
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <vector>
#include "mvm/Threads/Locks.h"
#include "VMClass.h"
#include "VMObject.h"
#include "VMThread.h"
#include "VirtualMachine.h"
using namespace n3;
void VMObject::initialise(VMCommonClass* cl) {
this->classOf = cl;
this->lockObj = 0;
}
VMCond* VMCond::allocate() {
return gc_new(VMCond)();
}
void VMCond::notify() {
for (std::vector<VMThread*>::iterator i = threads.begin(),
e = threads.end(); i!= e; ++i) {
VMThread* cur = *i;
cur->lock->lock();
if (cur->interruptFlag != 0) {
cur->lock->unlock();
continue;
} else if (cur->vmThread != 0) {
cur->varcond->signal();
cur->lock->unlock();
threads.erase(i);
break;
} else { // dead thread
threads.erase(i);
}
}
}
void VMCond::notifyAll() {
for (std::vector<VMThread*>::iterator i = threads.begin(),
e = threads.end(); i!= e; ++i) {
VMThread* cur = *i;
cur->lock->lock();
cur->varcond->signal();
cur->lock->unlock();
threads.erase(i);
}
}
void VMCond::wait(VMThread* th) {
threads.push_back(th);
}
void VMCond::remove(VMThread* th) {
for (std::vector<VMThread*>::iterator i = threads.begin(),
e = threads.end(); i!= e; ++i) {
if (*i == th) {
threads.erase(i);
break;
}
}
}
void LockObj::print(mvm::PrintBuffer* buf) const {
buf->write("Lock<>");
}
LockObj* LockObj::allocate() {
LockObj* res = gc_new(LockObj)();
res->lock = mvm::Lock::allocRecursive();
res->varcond = VMCond::allocate();
return res;
}
void LockObj::aquire() {
lock->lock();
}
void LockObj::release() {
lock->unlock();
}
bool LockObj::owner() {
return mvm::Lock::selfOwner(lock);
}
void VMObject::print(mvm::PrintBuffer* buf) const {
buf->write("VMObject<");
classOf->print(buf);
buf->write(">");
}
VMObject* VMObject::allocate(VMCommonClass* cl) {
VMObject* res = gc_new(VMObject)();
res->classOf = cl;
return res;
}
static LockObj* myLock(VMObject* obj) {
verifyNull(obj);
if (obj->lockObj == 0) {
VMObject::globalLock->lock();
if (obj->lockObj == 0) {
obj->lockObj = LockObj::allocate();
}
VMObject::globalLock->unlock();
}
return obj->lockObj;
}
void VMObject::aquire() {
myLock(this)->aquire();
}
void VMObject::unlock() {
verifyNull(this);
lockObj->release();
}
void VMObject::waitIntern(struct timeval* info, bool timed) {
LockObj * l = myLock(this);
bool owner = l->owner();
if (owner) {
VMThread* thread = VMThread::get();
mvm::Lock* mutexThread = thread->lock;
mvm::Cond* varcondThread = thread->varcond;
mutexThread->lock();
if (thread->interruptFlag != 0) {
mutexThread->unlock();
thread->interruptFlag = 0;
thread->vm->interruptedException(this);
} else {
unsigned int recur = mvm::LockRecursive::recursion_count(l->lock);
bool timeout = false;
mvm::LockRecursive::my_unlock_all(l->lock);
l->varcond->wait(thread);
thread->state = VMThread::StateWaiting;
if (timed) {
timeout = varcondThread->timed_wait(mutexThread, info);
} else {
varcondThread->wait(mutexThread);
}
bool interrupted = (thread->interruptFlag != 0);
mutexThread->unlock();
mvm::LockRecursive::my_lock_all(l->lock, recur);
if (interrupted || timeout) {
l->varcond->remove(thread);
}
thread->state = VMThread::StateRunning;
if (interrupted) {
thread->interruptFlag = 0;
thread->vm->interruptedException(this);
}
}
} else {
VMThread::get()->vm->illegalMonitorStateException(this);
}
}
void VMObject::wait() {
waitIntern(0, false);
}
void VMObject::timedWait(struct timeval& info) {
waitIntern(&info, false);
}
void VMObject::notify() {
LockObj* l = myLock(this);
if (l->owner()) {
l->varcond->notify();
} else {
VMThread::get()->vm->illegalMonitorStateException(this);
}
}
void VMObject::notifyAll() {
LockObj* l = myLock(this);
if (l->owner()) {
l->varcond->notifyAll();
} else {
VMThread::get()->vm->illegalMonitorStateException(this);
}
}
bool VMObject::instanceOf(VMCommonClass* cl) {
if (!this) return false;
else return this->classOf->isAssignableFrom(cl);
}