#pragma once // ILink members must be public template struct ILink { static const UInt32 s_offset; ILink * next; ILink * prev; T * GetObj(void) { return (T *)(((uintptr_t)this) - s_offset); } static ILink * GetLink(T * obj) { return (ILink *)(((uintptr_t)obj) + s_offset); } void Unlink(void) { if(next) next->prev = prev; if(prev) prev->next = next; next = prev = NULL; } void LinkBefore(T * obj) { LinkBefore(GetLink(obj)); } void LinkAfter(T * obj) { LinkAfter(GetLink(obj)); } void LinkBefore(ILink * link) { link->next = this; link->prev = prev; if(prev) { prev->next = link; } prev = link; } void LinkAfter(ILink * link) { link->next = next; link->prev = this; if(next) { next->prev = link; } next = link; } }; template struct ILinkedList { ILink begin; ILink end; void Reset(void) { begin.next = &end; begin.prev = NULL; end.next = NULL; end.prev = &begin; } void PushFront(T * obj) { ILink * objLink = ILink ::GetLink(obj); objLink->next = begin.next; objLink->prev = &begin; if(objLink->next) { objLink->next->prev = objLink; } begin.next = objLink; } }; #define ILINK_INIT(baseType, memberName) template const UInt32 ILink ::s_offset = offsetof(baseType, memberName)