#ifndef XRPL_BASICS_COUNTEDOBJECT_H_INCLUDED #define XRPL_BASICS_COUNTEDOBJECT_H_INCLUDED #include #include #include #include #include namespace ripple { /** Manages all counted object types. */ class CountedObjects { public: static CountedObjects& getInstance() noexcept; using Entry = std::pair; using List = std::vector; List getCounts(int minimumThreshold) const; public: /** Implementation for @ref CountedObject. @internal */ class Counter { public: Counter(std::string name) noexcept : name_(std::move(name)), count_(0) { // Insert ourselves at the front of the lock-free linked list CountedObjects& instance = CountedObjects::getInstance(); Counter* head; do { head = instance.m_head.load(); next_ = head; } while (instance.m_head.exchange(this) != head); ++instance.m_count; } ~Counter() noexcept = default; int increment() noexcept { return ++count_; } int decrement() noexcept { return --count_; } int getCount() const noexcept { return count_.load(); } Counter* getNext() const noexcept { return next_; } std::string const& getName() const noexcept { return name_; } private: std::string const name_; std::atomic count_; Counter* next_; }; private: CountedObjects() noexcept; ~CountedObjects() noexcept = default; private: std::atomic m_count; std::atomic m_head; }; //------------------------------------------------------------------------------ /** Tracks the number of instances of an object. Derived classes have their instances counted automatically. This is used for reporting purposes. @ingroup ripple_basics */ template class CountedObject { private: static auto& getCounter() noexcept { static CountedObjects::Counter c{beast::type_name()}; return c; } public: CountedObject() noexcept { getCounter().increment(); } CountedObject(CountedObject const&) noexcept { getCounter().increment(); } CountedObject& operator=(CountedObject const&) noexcept = default; ~CountedObject() noexcept { getCounter().decrement(); } }; } // namespace ripple #endif