/* * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version. * Copyright (C) 2008-2016 TrinityCore * Copyright (C) 2005-2009 MaNGOS */ #ifndef _REFERENCE_H #define _REFERENCE_H #include "Dynamic/LinkedList.h" #include "Errors.h" // for ASSERT //===================================================== template class Reference : public LinkedListElement { private: TO* iRefTo; FROM* iRefFrom; protected: // Tell our refTo (target) object that we have a link virtual void targetObjectBuildLink() = 0; // Tell our refTo (taget) object, that the link is cut virtual void targetObjectDestroyLink() = 0; // Tell our refFrom (source) object, that the link is cut (Target destroyed) virtual void sourceObjectDestroyLink() = 0; public: Reference() { iRefTo = nullptr; iRefFrom = nullptr; } virtual ~Reference() = default; // Create new link void link(TO* toObj, FROM* fromObj) { ASSERT(fromObj); // fromObj MUST not be nullptr if (isValid()) unlink(); if (toObj != nullptr) { iRefTo = toObj; iRefFrom = fromObj; targetObjectBuildLink(); } } // We don't need the reference anymore. Call comes from the refFrom object // Tell our refTo object, that the link is cut void unlink() { targetObjectDestroyLink(); delink(); iRefTo = nullptr; iRefFrom = nullptr; } // Link is invalid due to destruction of referenced target object. Call comes from the refTo object // Tell our refFrom object, that the link is cut void invalidate() // the iRefFrom MUST remain!! { sourceObjectDestroyLink(); delink(); iRefTo = nullptr; } [[nodiscard]] bool isValid() const // Only check the iRefTo { return iRefTo != nullptr; } Reference* next() { return ((Reference*) LinkedListElement::next()); } [[nodiscard]] Reference const* next() const { return ((Reference const*) LinkedListElement::next()); } Reference* prev() { return ((Reference*) LinkedListElement::prev()); } [[nodiscard]] Reference const* prev() const { return ((Reference const*) LinkedListElement::prev()); } Reference* nocheck_next() { return ((Reference*) LinkedListElement::nocheck_next()); } [[nodiscard]] Reference const* nocheck_next() const { return ((Reference const*) LinkedListElement::nocheck_next()); } Reference* nocheck_prev() { return ((Reference*) LinkedListElement::nocheck_prev()); } [[nodiscard]] Reference const* nocheck_prev() const { return ((Reference const*) LinkedListElement::nocheck_prev()); } TO* operator ->() const { return iRefTo; } [[nodiscard]] TO* getTarget() const { return iRefTo; } [[nodiscard]] FROM* GetSource() const { return iRefFrom; } }; //===================================================== #endif