Implementing object table. Not complete, but better.
This commit is contained in:
@@ -26,14 +26,12 @@ namespace {
|
||||
|
||||
KernelState::KernelState(Runtime* runtime) :
|
||||
runtime_(runtime),
|
||||
executable_module_(NULL),
|
||||
next_handle_(0) {
|
||||
executable_module_(NULL) {
|
||||
memory_ = runtime->memory();
|
||||
processor_ = runtime->processor();
|
||||
filesystem_ = runtime->filesystem();
|
||||
|
||||
objects_mutex_ = xe_mutex_alloc(0);
|
||||
XEASSERTNOTNULL(objects_mutex_);
|
||||
object_table_ = new ObjectTable();
|
||||
}
|
||||
|
||||
KernelState::~KernelState() {
|
||||
@@ -43,27 +41,7 @@ KernelState::~KernelState() {
|
||||
}
|
||||
|
||||
// Delete all objects.
|
||||
// We first copy the list to another list so that the deletion of the objects
|
||||
// doesn't mess up iteration.
|
||||
std::vector<XObject*> all_objects;
|
||||
xe_mutex_lock(objects_mutex_);
|
||||
for (std::tr1::unordered_map<X_HANDLE, XObject*>::iterator it =
|
||||
objects_.begin(); it != objects_.end(); ++it) {
|
||||
all_objects.push_back(it->second);
|
||||
}
|
||||
objects_.clear();
|
||||
modules_.clear();
|
||||
threads_.clear();
|
||||
xe_mutex_unlock(objects_mutex_);
|
||||
for (std::vector<XObject*>::iterator it = all_objects.begin();
|
||||
it != all_objects.end(); ++it) {
|
||||
// Perhaps call a special ForceRelease method or something?
|
||||
XObject* obj = *it;
|
||||
delete obj;
|
||||
}
|
||||
|
||||
xe_mutex_free(objects_mutex_);
|
||||
objects_mutex_ = NULL;
|
||||
delete object_table_;
|
||||
|
||||
filesystem_.reset();
|
||||
processor_.reset();
|
||||
@@ -86,75 +64,31 @@ fs::FileSystem* KernelState::filesystem() {
|
||||
return filesystem_.get();
|
||||
}
|
||||
|
||||
// TODO(benvanik): invesitgate better handle storage/structure.
|
||||
// A much better way of doing handles, if performance becomes an issue, would
|
||||
// be to try to make the pointers 32bit. Then we could round-trip them through
|
||||
// PPC code without needing to keep a map.
|
||||
// To achieve this we could try doing allocs in the 32-bit address space via
|
||||
// the OS alloc calls, or maybe create a section with a reserved size at load
|
||||
// time (65k handles * 4 is more than enough?).
|
||||
// We could then use a free list of handle IDs and allocate/release lock-free.
|
||||
|
||||
XObject* KernelState::GetObject(X_HANDLE handle) {
|
||||
xe_mutex_lock(objects_mutex_);
|
||||
std::tr1::unordered_map<X_HANDLE, XObject*>::iterator it =
|
||||
objects_.find(handle);
|
||||
XObject* value = it != objects_.end() ? it->second : NULL;
|
||||
if (value) {
|
||||
value->Retain();
|
||||
}
|
||||
xe_mutex_unlock(objects_mutex_);
|
||||
return value;
|
||||
}
|
||||
|
||||
X_HANDLE KernelState::InsertObject(XObject* obj) {
|
||||
xe_mutex_lock(objects_mutex_);
|
||||
X_HANDLE handle = 0x00001000 + (++next_handle_);
|
||||
objects_.insert(std::pair<X_HANDLE, XObject*>(handle, obj));
|
||||
switch (obj->type()) {
|
||||
case XObject::kTypeModule:
|
||||
modules_.insert(std::pair<X_HANDLE, XModule*>(
|
||||
handle, static_cast<XModule*>(obj)));
|
||||
break;
|
||||
case XObject::kTypeThread:
|
||||
threads_.insert(std::pair<X_HANDLE, XThread*>(
|
||||
handle, static_cast<XThread*>(obj)));
|
||||
break;
|
||||
}
|
||||
xe_mutex_unlock(objects_mutex_);
|
||||
return handle;
|
||||
}
|
||||
|
||||
void KernelState::RemoveObject(XObject* obj) {
|
||||
xe_mutex_lock(objects_mutex_);
|
||||
objects_.erase(obj->handle());
|
||||
xe_mutex_unlock(objects_mutex_);
|
||||
ObjectTable* KernelState::object_table() const {
|
||||
return object_table_;
|
||||
}
|
||||
|
||||
XModule* KernelState::GetModule(const char* name) {
|
||||
XModule* found = NULL;
|
||||
xe_mutex_lock(objects_mutex_);
|
||||
for (std::tr1::unordered_map<X_HANDLE, XModule*>::iterator it =
|
||||
modules_.begin(); it != modules_.end(); ++it) {
|
||||
if (xestrcmpa(name, it->second->name()) == 0) {
|
||||
found = it->second;
|
||||
found->Retain();
|
||||
}
|
||||
}
|
||||
xe_mutex_unlock(objects_mutex_);
|
||||
return found;
|
||||
}
|
||||
|
||||
XModule* KernelState::GetExecutableModule() {
|
||||
if (executable_module_) {
|
||||
executable_module_->Retain();
|
||||
return executable_module_;
|
||||
}
|
||||
// TODO(benvanik): implement lookup. Most games seem to look for xam.xex/etc.
|
||||
XEASSERTALWAYS();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XModule* KernelState::GetExecutableModule() {
|
||||
if (!executable_module_) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
executable_module_->Retain();
|
||||
return executable_module_;
|
||||
}
|
||||
|
||||
void KernelState::SetExecutableModule(XModule* module) {
|
||||
if (executable_module_ && executable_module_ != module) {
|
||||
if (module == executable_module_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (executable_module_) {
|
||||
executable_module_->Release();
|
||||
}
|
||||
executable_module_ = module;
|
||||
|
||||
Reference in New Issue
Block a user