/* * Copyright (C) 2012-2017 CypherCore * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using Framework.Collections; using System.Diagnostics.Contracts; namespace Framework.Dynamic { public class Reference : LinkedListElement where TO : class where FROM : class { TO _RefTo; FROM _RefFrom; // Tell our refTo (target) object that we have a link public virtual void targetObjectBuildLink() { } // Tell our refTo (taget) object, that the link is cut public virtual void targetObjectDestroyLink() { } // Tell our refFrom (source) object, that the link is cut (Target destroyed) public virtual void sourceObjectDestroyLink() { } public Reference() { _RefTo = null; _RefFrom = null; } // Create new link public void link(TO toObj, FROM fromObj) { Contract.Assert(fromObj != null); // fromObj MUST not be NULL if (isValid()) unlink(); if (toObj != null) { _RefTo = toObj; _RefFrom = fromObj; targetObjectBuildLink(); } } // We don't need the reference anymore. Call comes from the refFrom object // Tell our refTo object, that the link is cut public void unlink() { targetObjectDestroyLink(); delink(); _RefTo = null; _RefFrom = null; } // 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 public void invalidate() // the iRefFrom MUST remain!! { sourceObjectDestroyLink(); delink(); _RefTo = null; } public bool isValid() // Only check the iRefTo { return _RefTo != null; } public Reference next() { return ((Reference)GetNextElement()); } public Reference prev() { return ((Reference)GetPrevElement()); } public TO getTarget() { return _RefTo; } public FROM GetSource() { return _RefFrom; } } public class RefManager : LinkedListHead where TO : class where FROM : class { ~RefManager() { clearReferences(); } public Reference getFirst() { return (Reference)base.GetFirstElement(); } public Reference getLast() { return (Reference)base.GetLastElement(); } public void clearReferences() { LinkedListElement curr; while ((curr = base.GetFirstElement()) != null) { ((Reference)curr).invalidate(); curr.delink(); // the delink might be already done by invalidate(), but doing it here again does not hurt and insures an empty list } } } }