Mercurial > hg > svcore
view base/ById.cpp @ 1742:52705a328b34 by-id
Rejig ById so as to put everything in a single pool, so that at the core you can go from numeric id (untyped) to anything the object can be dynamic_cast to. Useful for building other abstractions like PlayParameter-type registrations that don't know about e.g. Models. Probably some more tweaking needed. Also add tests
author | Chris Cannam |
---|---|
date | Fri, 28 Jun 2019 17:36:30 +0100 |
parents | |
children | b92bdcd4954b |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Sonic Visualiser An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "ById.h" #include <unordered_map> #include <typeinfo> int IdAlloc::getNextId() { static int nextId = 0; static QMutex mutex; QMutexLocker locker(&mutex); int i = nextId; if (nextId == INT_MAX) { nextId = INT_MIN; } else { ++nextId; if (nextId == 0 || nextId == NO_ID) { throw std::runtime_error("Internal ID limit exceeded!"); } } return i; } class AnyById::Impl { public: ~Impl() { QMutexLocker locker(&m_mutex); bool empty = true; for (const auto &p: m_items) { if (p.second && p.second.use_count() > 0) { empty = false; break; } } if (!empty) { SVCERR << "WARNING: ById map is not empty at close; some items have not been released" << endl; SVCERR << " Unreleased items are:" << endl; for (const auto &p: m_items) { if (p.second && p.second.use_count() > 0) { SVCERR << " - id #" << p.first << ": type " << typeid(*p.second.get()).name() << ", use count " << p.second.use_count() << endl; } } } } void add(int id, std::shared_ptr<WithId> item) { QMutexLocker locker(&m_mutex); if (m_items.find(id) != m_items.end()) { SVCERR << "ById::add: item with id " << id << " is already recorded (existing item type is " << typeid(*m_items.find(id)->second.get()).name() << ", proposed is " << typeid(*item.get()).name() << ")" << endl; throw std::logic_error("item id is already recorded in add"); } m_items[id] = item; } void release(int id) { QMutexLocker locker(&m_mutex); if (m_items.find(id) == m_items.end()) { SVCERR << "ById::release: unknown item id " << id << endl; throw std::logic_error("unknown item id in release"); } m_items.erase(id); } std::shared_ptr<WithId> get(int id) const { QMutexLocker locker(&m_mutex); const auto &itr = m_items.find(id); if (itr != m_items.end()) { return itr->second; } else { return {}; } } private: mutable QMutex m_mutex; std::unordered_map<int, std::shared_ptr<WithId>> m_items; }; void AnyById::add(int id, std::shared_ptr<WithId> item) { impl().add(id, item); } void AnyById::release(int id) { impl().release(id); } std::shared_ptr<WithId> AnyById::get(int id) { return impl().get(id); } AnyById::Impl & AnyById::impl() { static Impl impl; return impl; }