KAI_BEGIN Pathname GetFullname(const Object &Q) { if (!Q.Valid()) return Pathname(); return GetFullname(GetStorageBase(Q)); }
void StorageBase::Set(const Label &name, Object const &child) { if (child.GetHandle() == GetHandle()) KAI_THROW_1(InternalError, "Recursion"); // mark the object as being altered SetDirty(); // set a property if it exists ClassBase const *klass = GetClass(); if (klass->HasProperty(name)) { klass->GetProperty(name).SetValue(*this, child); return; } // otherwise this is a child object. remove any existing child Remove(name); // update the child object if (!child.Exists()) { Dictionary::iterator ch = dictionary.find(name); if (ch != dictionary.end()) dictionary.erase(ch); return; } StorageBase &base = KAI_NAMESPACE(GetStorageBase(child)); base.SetLabel(name); base.SetParentHandle(GetHandle()); bool clean = base.IsClean(); bool konst = base.IsConst(); bool managed = base.IsManaged(); base.switches = switches; // inherit properties of parent... if (clean) // ...but preserve cleanliness base.switches |= IObject::Clean; else base.switches &= ~IObject::Clean; if (konst) // ...and constness base.switches |= IObject::Const; if (managed) // ...and managed base.switches |= IObject::Managed; // add it to this dictionary, inform it of being added to a container dictionary[name] = child; base.AddedToContainer(*this); }
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::MarkAll(StorageBase &root, bool marked) { MarkObject(root, marked); const Dictionary &dict = root.GetDictionary(); Dictionary::const_iterator C = dict.begin(), D = dict.end(); for (; C != D; ++C) { Object const &child = C->second; StorageBase *base = GetStorageBase(child.GetHandle()); if (base == 0) continue; if (base->IsManaged()) MarkObject(*base, marked); if (base->GetSwitches() & IObject::NoRecurse) continue; MarkAll(*base, marked); } }
Pathname GetFullname(const StorageBase &Q) { nstd::list<String> parentage; Label const &label = Q.GetLabel(); if (!label.ToString().empty()) parentage.push_back(label.ToString()); Object parent = Q.GetParent(); for (; parent.Valid(); parent = parent.GetParent()) parentage.push_front(GetStorageBase(parent).GetLabel().ToString()); StringStream path; if (!parentage.empty()) ;//path << "[anon]"; else path.Append('/'); foreach (String const &name, parentage) { path.Append(name); path.Append('/'); }