// This code contains NVIDIA Confidential Information and is disclosed to you // under a form of NVIDIA software license agreement provided separately to you. // // Notice // NVIDIA Corporation and its licensors retain all intellectual property and // proprietary rights in and to this software and related documentation and // any modifications thereto. Any use, reproduction, disclosure, or // distribution of this software and related documentation without an express // license agreement from NVIDIA Corporation is strictly prohibited. // // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. // // Information and code furnished is believed to be accurate and reliable. // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such // information or for any infringement of patents or other rights of third parties that may // result from its use. No license is granted by implication or otherwise under any patent // or patent rights of NVIDIA Corporation. Details are subject to change without notice. // This code supersedes and replaces all information previously supplied. // NVIDIA Corporation products are not authorized for use as critical // components in life support devices or systems without express written approval of // NVIDIA Corporation. // // Copyright (c) 2016-2020 NVIDIA Corporation. All rights reserved. #ifndef NVBLASTDLINK_H #define NVBLASTDLINK_H #include "NvBlastAssert.h" #include "NvBlastIndexFns.h" namespace Nv { namespace Blast { template struct IndexDLink { IndexType m_adj[2]; }; template class IndexDList { public: void initLinksSolitary(IndexDLink* links, IndexType linkCount) { for (IndexType i = 0; i < linkCount; ++i) { links[i].m_adj[0] = invalidIndex(); links[i].m_adj[1] = invalidIndex(); } } void initLinksChain(IndexDLink* links, IndexType linkCount) { if (linkCount > 0) { links[0].m_adj[0] = invalidIndex(); for (IndexType i = 1; i < linkCount; ++i) { links[i - 1].m_adj[1] = i; links[i].m_adj[0] = i - 1; } links[linkCount - 1].m_adj[1] = invalidIndex(); } } IndexType getAdj(IndexDLink* links, IndexType linkIndex, int which) { return links[linkIndex].m_adj[which & 1]; } void remove(IndexDLink* links, IndexType linkIndex) { IndexDLink& link = links[linkIndex]; const IndexType adj0 = link.m_adj[0]; const IndexType adj1 = link.m_adj[1]; if (!isInvalidIndex(adj1)) { links[adj1].m_adj[0] = adj0; link.m_adj[1] = invalidIndex(); } if (!isInvalidIndex(adj0)) { links[adj0].m_adj[1] = adj1; link.m_adj[0] = invalidIndex(); } } bool isSolitary(IndexDLink* links, IndexType linkIndex) { const IndexDLink& link = links[linkIndex]; return isInvalidIndex(link.m_adj[0]) && isInvalidIndex(link.m_adj[1]); } void insertListHead(IndexType& listHead, IndexDLink* links, IndexType linkIndex) { NVBLAST_ASSERT(!isInvalidIndex(linkIndex)); if (!isInvalidIndex(listHead)) { links[listHead].m_adj[0] = linkIndex; } links[linkIndex].m_adj[1] = listHead; listHead = linkIndex; } IndexType removeListHead(IndexType& listHead, IndexDLink* links) { const IndexType linkIndex = listHead; if (!isInvalidIndex(linkIndex)) { listHead = links[linkIndex].m_adj[1]; if (!isInvalidIndex(listHead)) { links[listHead].m_adj[0] = invalidIndex(); } links[linkIndex].m_adj[1] = invalidIndex(); } return linkIndex; } void removeFromList(IndexType& listHead, IndexDLink* links, IndexType linkIndex) { NVBLAST_ASSERT(!isInvalidIndex(linkIndex)); if (listHead == linkIndex) { listHead = links[linkIndex].m_adj[1]; } remove(links, linkIndex); } }; struct DLink { DLink() : m_prev(nullptr), m_next(nullptr) {} DLink* getPrev() const { return m_prev; } DLink* getNext() const { return m_next; } private: DLink* m_prev; DLink* m_next; friend class DList; }; class DList { public: DList() : m_head(nullptr), m_tail(nullptr) {} bool isEmpty() const { NVBLAST_ASSERT((m_head == nullptr) == (m_tail == nullptr)); return m_head == nullptr; } bool isSolitary(const DLink& link) const { return link.m_prev == nullptr && link.m_next == nullptr && m_head != &link; } DLink* getHead() const { return m_head; } DLink* getTail() const { return m_tail; } bool insertHead(DLink& link) { NVBLAST_ASSERT(isSolitary(link)); if (!isSolitary(link)) { return false; } link.m_next = m_head; if (m_head != nullptr) { m_head->m_prev = &link; } m_head = &link; if (m_tail == nullptr) { m_tail = &link; } return true; } bool insertTail(DLink& link) { NVBLAST_ASSERT(isSolitary(link)); if (!isSolitary(link)) { return false; } link.m_prev = m_tail; if (m_tail != nullptr) { m_tail->m_next = &link; } m_tail = &link; if (m_head == nullptr) { m_head = &link; } return true; } void remove(DLink& link) { if (link.m_prev != nullptr) { link.m_prev->m_next = link.m_next; } else if (m_head == &link) { m_head = link.m_next; } if (link.m_next != nullptr) { link.m_next->m_prev = link.m_prev; } else if (m_tail == &link) { m_tail = link.m_prev; } link.m_next = link.m_prev = nullptr; } class It { public: enum Direction { Reverse, Forward }; It(const DList& list, Direction dir = Forward) : m_curr(dir == Forward ? list.getHead() : list.getTail()) {} /** Validity of current value. */ operator bool() const { return m_curr != nullptr; } /** Current value. */ operator const DLink*() const { return m_curr; } /** Pre-increment. */ const DLink* operator ++ () { return m_curr = m_curr->getNext(); } /** Pre-deccrement. */ const DLink* operator -- () { return m_curr = m_curr->getPrev(); } private: const DLink* m_curr; }; private: DLink* m_head; DLink* m_tail; }; } // end namespace Blast } // end namespace Nv #endif // #ifndef NVBLASTDLINK_H