void Registry::Delete(Object const &object) { #ifdef KAI_DEBUG if (IsWatching(object)) KAI_TRACE() << object.GetHandle(); #endif Delete(object.GetHandle()); }
Object Registry::GetObject(Handle handle) const { #ifdef KAI_DEBUG if (IsWatching(handle) && gc_trace_level > 1) KAI_TRACE() << handle; #endif if (handle == 0) return Object(); Instances::const_iterator A = instances.find(handle); if (A == instances.end()) return Object(); return *A->second; }
void Registry::TriColor() { // this is a magic number. the higher it is, the more objects may be deleted in this call // the cost has to be paid at some point, so this number really means "how much do I want // to spread out cost of GC over time versus memory use". // // if you have lots of memory, set max_cycles to 1. (or zero!). if not, set it higher // until you can fit memory usage into a sequence of frames. // // see also https://github.com/cschladetsch/Monotonic const int max_cycles = 17; if (gc_trace_level >= 1) { KAI_TRACE_3(instances.size(), grey.size(), white.size()); } int cycle = 0; for (; cycle < max_cycles; ++cycle) { #ifdef KAI_DEBUG_REGISTRY if (gc_trace_level > 2) TraceTriColor(); #endif if (grey.empty()) { ReleaseWhite(); break; } ColoredSet::iterator iter = grey.begin(); Handle handle = *iter; grey.erase(iter); StorageBase *base = GetStorageBase(handle); if (base == 0) continue; base->MakeReachableGrey(); base->SetColor(ObjectColor::Black); } if (gc_trace_level >= 1) KAI_TRACE() << "TriColor: " << cycle << " passes"; }
void Registry::Delete(Handle handle) { #ifdef KAI_USE_TRICOLOR // use Object::Delete (void)handle; throw; #else #ifdef KAI_DEBUG if (IsObserving(handle)) { KAI_TRACE() << handle; } #endif // if unknown handle, do nothing Instances::const_iterator instance = instances.find(handle); if (instance == instances.end()) return; // detach from parent if (instance->second) { StorageBase &storage = *instance->second; storage.SetColor(ObjectColor::White); storage.SetColorRecursive(ObjectColor::White); storage.GetClass()->Destroy(storage); //Detach(storage); } // remove from list of retained objects auto etained = retained_objects.find(handle); if (retained != retained_objects.end()) retained_objects.erase(retained); // mark for pending collection #ifndef KAI_USE_TRICOLOR deathrow.insert(handle); #endif #endif }
Object Registry::NewFromClass(const ClassBase *klass) { if (klass == 0) KAI_THROW_1(UnknownClass<>, "NULL Class"); Handle handle = next_handle.NextValue(); StorageBase *base = 0; base = klass->NewStorage(this, handle); #ifdef KAI_DEBUG_REGISTRY if (IsWatchingType(klass->GetTypeNumber())) KAI_TRACE() << klass->GetName() << ": " << handle; #endif base->SetColor(ObjectColor::White); base->SetMarked(false); instances[handle] = base; klass->Create(*base); return Object(ObjectConstructParams(this, klass, handle)); }
void Registry::DestroyObject(Handle handle, bool force) { bool succeeded = false; KAI_TRY { Instances::iterator iter = instances.find(handle); if (iter == instances.end()) { #ifdef KAI_DEBUG if (IsWatching(handle)) { KAI_TRACE() << handle << ": doesn't exist, not deleted"; } #endif return; } StorageBase &base = *iter->second; assert(base.GetHandle() == handle); if (!base.IsManaged() && !force) { #ifdef KAI_DEBUG if (IsWatching(handle)) KAI_TRACE() << handle << ": " << base << " is not managed, not deleted"; #endif return; } #ifdef KAI_DEBUG bool trace = gc_trace_level > 3; trace = trace || IsWatching(base); if (trace) { KAI_TRY { KAI_TRACE() << handle; } KAI_CATCH_ALL() { } } #endif #ifdef KAI_USE_TRICOLOR // when using tri-color GC, objects are always deleted when they are destroyed if (!base.GetClass()->Destroy(base) && !force) { base.SetColor(ObjectColor::Grey); return; } #endif base.GetClass()->Delete(base); instances.erase(iter); RetainedObjects::iterator retained = retained_objects.find(handle); if (retained != retained_objects.end()) { retained_objects.erase(retained); } succeeded = true; } KAI_CATCH(Exception::Base, E) { KAI_TRACE() << "\n\t" << E.ToString(); } KAI_CATCH(std::exception, E) { KAI_TRACE() << "std::exception: " << E.what(); } KAI_CATCH_ALL() { } if (!succeeded) { KAI_TRACE() << "*** AWESOMELY BAD EXCEPTION deleting object ***"; Instances::iterator iter = instances.find(handle); if (iter != instances.end()) { // this leaks and has other *TERRIBLE* consequences but it is the best we can do to keep afloat instances.erase(iter); } } }
KAI_CATCH(std::exception, E) { KAI_UNUSED(E); KAI_TRACE() << "std::exception: " << E.what(); }
void Registry::DestroyObject(Handle handle, bool force) { bool succeeded = false; KAI_TRY { Instances::iterator iter = instances.find(handle); if (iter == instances.end()) { #ifdef KAI_DEBUG_REGISTRY if (IsWatching(handle)) { KAI_TRACE() << handle << ": doesn't exist, not deleted"; } #endif return; } StorageBase &base = *iter->second; assert(base.GetHandle() == handle); if (!base.IsManaged() && !force) { #ifdef KAI_DEBUG_REGISTRY if (IsWatching(handle)) KAI_TRACE() << handle << ": " << base << " is not managed, not deleted"; #endif return; } #ifdef KAI_DEBUG_REGISTRY bool trace = gc_trace_level > 3; trace = trace || IsWatching(base); if (trace) { KAI_TRY { KAI_TRACE() << handle; } KAI_CATCH_ALL() { } } #endif #ifdef KAI_USE_TRICOLOR // when using tri-color GC, objects are always deleted when they are destroyed if (!base.GetClass()->Destroy(base) && !force) { base.SetColor(ObjectColor::Grey); return; } #endif base.GetClass()->Delete(base); instances.erase(iter); RetainedObjects::iterator retained = retained_objects.find(handle); if (retained != retained_objects.end()) { retained_objects.erase(retained); } succeeded = true; } KAI_CATCH(Exception::Base, E) { KAI_UNUSED(E); KAI_TRACE() << "\n\t" << E.ToString(); }