void recycle(GarbageDestructor condition = 0) { DENG2_GUARD(this); if (allocs.empty()) return; #ifdef DENG2_DEBUG //qDebug() << "[Garbage] Recycling" << allocs.size() << "allocs/objects"; #endif for (Allocs::iterator i = allocs.begin(); i != allocs.end(); ) { Allocs::iterator next = i; ++next; DENG2_ASSERT(i->second); if (!condition || i->second == condition) { i->second(i->first); // Erase one by one if a condition has been given. if (condition) allocs.erase(i); } i = next; } if (!condition) { // All can be erased as we have no condition. allocs.clear(); } }
bool contains(void const *ptr) const { DENG2_GUARD(this); Allocs::const_iterator i = allocs.find(const_cast<void *>(ptr)); return i != allocs.end(); }
bool PathTree::has(Path const &path, ComparisonFlags flags) const { DENG2_GUARD(this); flags &= ~RelinquishMatching; // never relinquish return d->find(path, flags) != 0; }
void MemoryLogSink::clear() { DENG2_GUARD(this); qDeleteAll(_entries); _entries.clear(); }
void NativeFile::flush() { DENG2_GUARD(this); d->closeOutput(); DENG2_ASSERT(!d->out); }
void NativeFile::set(Offset at, Byte const *values, Size count) { DENG2_GUARD(this); QFile &out = output(); if (at > size()) { /// @throw IByteArray::OffsetError @a at specified a position beyond the /// end of the file. throw OffsetError("NativeFile::set", "Cannot write past end of file"); } out.seek(at); out.write(reinterpret_cast<char const *>(values), count); if (out.error() != QFile::NoError) { /// @throw OutputError Failure to write to the native file. throw OutputError("NativeFile::set", "Error writing to file:" + out.errorString()); } // Update status. Status st = status(); st.size = max(st.size, at + count); st.modifiedAt = Time(); setStatus(st); }
void recycleWithDestructor(GarbageDestructor func) { DENG2_GUARD(this); for (iterator i = begin(); i != end(); ++i) { i->second->recycle(func); } }
void LoopCallback::enqueue(Callback func) { DENG2_GUARD(this); _funcs << func; Loop::get().audienceForIteration() += this; }
BusyRunner::DeferredResult performDeferredGLTask() override { initPendingModels(1); DENG2_GUARD(pendingModels); return pendingModels.value.isEmpty()? BusyRunner::AllTasksCompleted : BusyRunner::TasksPending; }
ArchiveEntryFile::~ArchiveEntryFile() { DENG2_GUARD(this); DENG2_FOR_AUDIENCE2(Deletion, i) i->fileBeingDeleted(*this); audienceForDeletion().clear(); deindex(); }
void MemoryLogSink::remove(int pos, int n) { DENG2_GUARD(this); while(n-- > 0) { delete _entries.takeAt(pos); } }
void clearAll() { DENG2_GUARD(this); for (iterator i = begin(); i != end(); ++i) { delete i->second; } clear(); }
LogSink &MemoryLogSink::operator << (LogEntry const &entry) { if(entry.level() >= _minLevel) { DENG2_GUARD(this); _entries.append(new LogEntry(entry)); addedNewEntry(*_entries.back()); } return *this; }
File &LinkFile::target() { DENG2_GUARD(this); if (d->target) { return *const_cast<File *>(d->target.get()); } return File::target(); }
File const &LinkFile::target() const { DENG2_GUARD(this); if (d->target) { return *d->target; } return File::target(); }
String LinkFile::describe() const { DENG2_GUARD(this); if (!isBroken()) { DENG2_GUARD_FOR(target(), G); return "link to " + target().description(); } return "broken link"; }
void NativeFile::clear() { DENG2_GUARD(this); File::clear(); Flags oldMode = mode(); setMode(Write | Truncate); d->getOutput(); File::setMode(oldMode); }
void NativeFile::setMode(Flags const &newMode) { DENG2_GUARD(this); close(); File::setMode(newMode); if (newMode.testFlag(Truncate)) { d->needTruncation = true; } }
PathTree::Node const &PathTree::find(Path const &searchPath, ComparisonFlags flags) const { DENG2_GUARD(this); Node const *found = d->find(searchPath, flags); if(!found) { /// @throw NotFoundError The referenced node could not be found. throw NotFoundError("PathTree::find", "No paths found matching \"" + searchPath + "\""); } return *found; }
PathTree::Node &PathTree::insert(Path const &path) { DENG2_GUARD(this); PathTree::Node *node = d->buildNodesForPath(path); DENG2_ASSERT(node != 0); // There is now one more unique path in the tree. d->size++; return *node; }
void ArchiveEntryFile::clear() { DENG2_GUARD(this); File::clear(); archive().entryBlock(_entryPath).clear(); // Update status. Status st = status(); st.size = 0; st.modifiedAt = Time(); setStatus(st); }
String ArchiveFolder::describe() const { DENG2_GUARD(this); String desc = String("archive \"%1\"").arg(name()); String const feedDesc = describeFeeds(); if(!feedDesc.isEmpty()) { desc += String(" (%1)").arg(feedDesc); } return desc; }
void NativeFile::get(Offset at, Byte *values, Size count) const { DENG2_GUARD(this); QFile &in = input(); if(at + count > size()) { /// @throw IByteArray::OffsetError The region specified for reading extends /// beyond the bounds of the file. throw OffsetError("NativeFile::get", description() + ": cannot read past end of file " + String("(%1[+%2] > %3)").arg(at).arg(count).arg(size())); } in.seek(at); in.read(reinterpret_cast<char *>(values), count); }
bool PathTree::remove(Path const &path, ComparisonFlags flags) { DENG2_GUARD(this); PathTree::Node *node = d->find(path, flags | RelinquishMatching); if(node) { delete node; // One less unique path in the tree. d->size--; return true; } return false; }
void ArchiveEntryFile::set(Offset at, Byte const *values, Size count) { DENG2_GUARD(this); verifyWriteAccess(); // The entry will be marked for recompression (due to non-const access). Block &entryBlock = archive().entryBlock(_entryPath); entryBlock.set(at, values, count); // Update status. Status st = status(); st.size = entryBlock.size(); st.modifiedAt = Time(); setStatus(st); }
void ArchiveEntryFile::set(Offset at, Byte const *values, Size count) { DENG2_GUARD(this); verifyWriteAccess(); // The entry will be marked for recompression (due to non-const access). Block &entryBlock = archive().entryBlock(_entryPath); entryBlock.set(at, values, count); // Update status. Status st = status(); st.size = entryBlock.size(); // Timestamps must match, otherwise would be pruned needlessly. st.modifiedAt = archive().entryStatus(_entryPath).modifiedAt; setStatus(st); }
void assetAvailabilityChanged(String const &identifier, filesys::AssetObserver::Event event) override { LOG_RES_MSG("Model asset \"%s\" is now %s") << identifier << (event == filesys::AssetObserver::Added? "available" : "unavailable"); if (event == filesys::AssetObserver::Added) { bank.add(identifier, App::asset(identifier).absolutePath("path")); // Begin loading the model right away. bank.load(identifier); } else { auto const &model = bank.model<render::Model const>(identifier); // Unload programs used by the various rendering passes. for (auto const &pass : model.passes) { DENG2_ASSERT(pass.program); unloadProgram(*static_cast<Program *>(pass.program)); } // Alternatively, the entire model may be using a single program. if (model.passes.isEmpty()) { if (model.program()) { unloadProgram(*static_cast<Program *>(model.program())); } } else { DENG2_ASSERT(!model.program()); } bank.remove(identifier); { DENG2_GUARD(pendingModels); pendingModels.value.remove(identifier); } } }
void LoopCallback::loopIteration() { QList<Callback> funcs; // Lock while modifying but not during the callbacks themselves. { DENG2_GUARD(this); Loop::get().audienceForIteration() -= this; // Make a copy of the list if new callbacks get enqueued in the callback. funcs = _funcs; _funcs.clear(); } for (Callback const &cb : funcs) { cb(); } }
void NativeFile::get(Offset at, Byte *values, Size count) const { DENG2_GUARD(this); if (at + count > size()) { d->closeInput(); /// @throw IByteArray::OffsetError The region specified for reading extends /// beyond the bounds of the file. throw OffsetError("NativeFile::get", description() + ": cannot read past end of file " + String("(%1[+%2] > %3)").arg(at).arg(count).arg(size())); } QFile &in = input(); if (in.pos() != qint64(at)) in.seek(qint64(at)); in.read(reinterpret_cast<char *>(values), count); // Close the native input file after reaching the end of the file. if (in.atEnd()) { d->closeInput(); } }
/** * Initializes one or more uninitialized models for rendering. * Must be called from the main thread. * * @param maxCount Maximum number of models to initialize. */ void initPendingModels(int maxCount) { DENG2_GUARD(pendingModels); while (!pendingModels.value.isEmpty() && maxCount > 0) { String const identifier = *pendingModels.value.begin(); pendingModels.value.remove(identifier); if (!bank.has(identifier)) { continue; } LOG_GL_MSG("Initializing \"%s\"") << identifier; auto &model = bank.model<render::Model>(identifier); model.glInit(); --maxCount; } }