/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkSparseFieldLayer_h #define itkSparseFieldLayer_h #include "itkObjectFactory.h" #include "itkObject.h" #include #include // For unique_ptr. namespace itk { /** * \class ConstSparseFieldLayerIterator * \brief Used to iterate through an itkSparseFieldLayer. * * This class is modeled on the STL Forward Iterator concept, and is used to * iterate through an itkSparseFieldLayer. * \ingroup ITKCommon */ template class ITK_TEMPLATE_EXPORT ConstSparseFieldLayerIterator { public: const TNodeType & operator*() const { return *m_Pointer; } const TNodeType * operator->() const { return m_Pointer; } const TNodeType * GetPointer() const { return m_Pointer; } bool operator==(const ConstSparseFieldLayerIterator o) const { if (m_Pointer == o.m_Pointer) { return true; } else { return false; } } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(ConstSparseFieldLayerIterator); ConstSparseFieldLayerIterator & operator++() { m_Pointer = m_Pointer->Next; return *this; } ConstSparseFieldLayerIterator & operator--() { m_Pointer = m_Pointer->Previous; return *this; } ConstSparseFieldLayerIterator() { m_Pointer = nullptr; } ConstSparseFieldLayerIterator(TNodeType * p) { m_Pointer = p; } ~ConstSparseFieldLayerIterator() = default; protected: TNodeType * m_Pointer; }; /** \class SparseFieldLayerIterator * \brief The non-const version of the ConstSparseFieldLayerIterator. * \ingroup ITKCommon */ template class ITK_TEMPLATE_EXPORT SparseFieldLayerIterator : public ConstSparseFieldLayerIterator { public: using Superclass = ConstSparseFieldLayerIterator; SparseFieldLayerIterator() : Superclass() {} SparseFieldLayerIterator(TNodeType * p) : Superclass(p) {} TNodeType & operator*() { return *this->m_Pointer; } TNodeType * operator->() { return this->m_Pointer; } TNodeType * GetPointer() { return this->m_Pointer; } SparseFieldLayerIterator & operator++() { this->m_Pointer = this->m_Pointer->Next; return *this; } SparseFieldLayerIterator & operator--() { this->m_Pointer = this->m_Pointer->Previous; return *this; } SparseFieldLayerIterator & operator=(Superclass & sc) { this->m_Pointer = const_cast(sc.GetPointer()); return *this; } }; /** \class SparseFieldLayer * \brief A very simple linked list that is used to manage * nodes in a layer of a sparse field level-set solver. * \par * This class implements a *very* simple linked list that is used to manage * nodes in a layer of a sparse field level-set solver. For more information * on the sparse field level-set solver, see documentation for * itk::SparseFieldLevelSetImageFilter. * * \par IMPORTANT! * One important and distinctive feature of this list implementation (in fact, * the entire reason for this object's existence) is that no memory * allocation/deallocation occurs during linking or unlinking of nodes. The * nodes themselves are expected to carry the appropriate "Next" & "Previous" * fields used to link. Guaranteeing that no calls to new or delete are * *ever* made for normal list operations allows us to safely use this class * in a multithread environment without incurring penalties from heap * contention among threads. Because no allocation/deallocation occurs, it is * entirely up to the calling program to manage the allocating and freeing of * the list nodes. * \ingroup ITKCommon */ template class ITK_TEMPLATE_EXPORT SparseFieldLayer : public Object { public: ITK_DISALLOW_COPY_AND_MOVE(SparseFieldLayer); /** Standard type alias. */ using Self = SparseFieldLayer; using Superclass = Object; using Pointer = SmartPointer; using ConstPointer = SmartPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(SparseFieldLayer); /** Type of node stored in the linked list. */ using NodeType = TNodeType; /** Alias for the type of value stored in the list. Conforms to Standard Template * Library vocabulary. */ using ValueType = NodeType; /** Iterator type for the list. */ using Iterator = SparseFieldLayerIterator; /** Const iterator type for the list. */ using ConstIterator = ConstSparseFieldLayerIterator; /** Regions used for multithreading */ struct RegionType { ConstIterator first; ConstIterator last; // this is one past the actual last element }; using RegionListType = std::vector; /** Returns a pointer to the first node in the list. Constant * time. */ NodeType * Front() { return m_HeadNode->Next; } /** Returns a const pointer to the first node in the list. Constant time. */ const NodeType * Front() const { return m_HeadNode->Next; } /** Unlinks the first node from the list. Constant time. */ void PopFront() { m_HeadNode->Next = m_HeadNode->Next->Next; m_HeadNode->Next->Previous = m_HeadNode.get(); m_Size -= 1; } /** Links a node into the front of the list. Constant time. */ void PushFront(NodeType * n) { n->Next = m_HeadNode->Next; n->Previous = m_HeadNode.get(); m_HeadNode->Next->Previous = n; m_HeadNode->Next = n; m_Size += 1; } /** Unlinks a node from the list */ void Unlink(NodeType * n) { n->Previous->Next = n->Next; n->Next->Previous = n->Previous; m_Size -= 1; } /** Returns an iterator pointing to the first node in the list. */ Iterator Begin() { return Iterator(m_HeadNode->Next); } /** Returns a const iterator pointing to the first node in the * list. */ ConstIterator Begin() const { return ConstIterator(m_HeadNode->Next); } /** Returns an iterator pointing one node past the end of the list. */ Iterator End() { return Iterator(m_HeadNode.get()); } /** Returns a const iterator pointing one node past the end of the list. */ ConstIterator End() const { return ConstIterator(m_HeadNode.get()); } /** Returns TRUE if the list is empty, FALSE otherwise. Executes in constant * time. */ bool Empty() const { if (m_HeadNode->Next == m_HeadNode.get()) { return true; } else { return false; } } /** Returns the number of elements in the list. Size() executes in constant * time. */ unsigned int Size() const; /** Returns pointers to first and last+1 elements of num partitions of the itkSparseFieldLayer */ RegionListType SplitRegions(int num) const; protected: SparseFieldLayer(); ~SparseFieldLayer() override = default; void PrintSelf(std::ostream & os, Indent indent) const override; private: /** The anchor node of the list. m_HeadNode->Next is the first node in the * list. If m_HeadNode->Next == m_HeadNode, then the list is empty. */ const std::unique_ptr m_HeadNode{ std::make_unique() }; unsigned int m_Size{}; }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkSparseFieldLayer.hxx" #endif #endif