Implementing object table. Not complete, but better.

This commit is contained in:
Ben Vanik
2013-09-22 18:36:06 -07:00
parent 3e0db586c0
commit d0d30ab719
7 changed files with 285 additions and 109 deletions

View File

@@ -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;