BVB Source Codes

CRYENGINE Show ParticleList.h Source code

Return Download CRYENGINE: download ParticleList.h Source code - Download CRYENGINE Source code - Type:.h
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #ifndef _CRY_PARTICLE_LIST_H_
  4. #define _CRY_PARTICLE_LIST_H_
  5. #pragma once
  6.  
  7. #include "ParticleMemory.h"
  8.  
  9. ////////////////////////////////////////////////////////////////////////
  10. // Bidirectional list
  11.  
  12. template<class T>
  13. class ParticleList
  14. {
  15. public:
  16.  
  17.         typedef T value_type;
  18.  
  19.         // Derived type with intrusive links after T, to preserve alignment
  20.         struct Node : T
  21.         {
  22.                 Node* pNext;
  23.                 Node* pPrev;
  24.         };
  25.  
  26.         ParticleList()
  27.         { reset(); }
  28.  
  29.         ~ParticleList()
  30.         { clear(); }
  31.  
  32.         bool   operator!() const
  33.         { return m_pHead == NULL; }
  34.         bool   empty() const
  35.         { return m_pHead == NULL; }
  36.         size_t size() const
  37.         { return m_nSize; }
  38.  
  39.         CONST_VAR_FUNCTION(T & front(),
  40.                            { assert(!empty()); return *m_pHead; })
  41.         CONST_VAR_FUNCTION(T & back(),
  42.                            { assert(!empty()); return *m_pTail; })
  43.  
  44.         //
  45.         // Iteration
  46.         //
  47.         template<typename CVT, bool bReverse = false>
  48.         struct cv_iterator
  49.         {
  50.                 typedef std::bidirectional_iterator_tag iterator_category;
  51.                 typedef ptrdiff_t                       difference_type;
  52.                 typedef ptrdiff_t                       distance_type;
  53.                 typedef T                               value_type;
  54.  
  55.                 cv_iterator(Node* p = NULL)
  56.                         : m_pNode(p) {}
  57.  
  58.                 operator bool() const
  59.                 { return !!m_pNode; }
  60.  
  61.                 CVT& operator*() const
  62.                 { assert(m_pNode); return *m_pNode; }
  63.                 CVT* operator->() const
  64.                 { assert(m_pNode); return m_pNode; }
  65.                 operator CVT*() const
  66.                 { assert(m_pNode); return m_pNode; }
  67.  
  68.                 void operator++()
  69.                 {
  70.                         if (bReverse)
  71.                                 m_pNode = m_pNode->pPrev;
  72.                         else
  73.                                 m_pNode = m_pNode->pNext;
  74.                 }
  75.  
  76.                 bool operator==(cv_iterator o) const
  77.                 { return m_pNode == o.m_pNode; }
  78.                 bool operator!=(cv_iterator o) const
  79.                 { return m_pNode != o.m_pNode; }
  80.  
  81.         protected:
  82.                 Node* m_pNode;
  83.         };
  84.  
  85.         // Non-const iterator has cached incrementation, allows safely erasing elements during iteration
  86.         template<bool bReverse = false>
  87.         struct v_iterator : cv_iterator<T, bReverse>
  88.         {
  89.                 typedef cv_iterator<T, bReverse> base;
  90.                 using base::m_pNode;
  91.  
  92.                 v_iterator(Node* p = NULL)
  93.                         : base(p)
  94.                 {
  95.                         set_next();
  96.                 }
  97.  
  98.                 void operator++()
  99.                 {
  100.                         m_pNode = m_pNext;
  101.                         set_next();
  102.                 }
  103.  
  104.         protected:
  105.                 Node* m_pNext;
  106.  
  107.                 void set_next()
  108.                 {
  109.                         if (m_pNode)
  110.                         {
  111.                                 if (bReverse)
  112.                                         m_pNext = m_pNode->pPrev;
  113.                                 else
  114.                                         m_pNext = m_pNode->pNext;
  115.                         }
  116.                 }
  117.         };
  118.  
  119.         typedef cv_iterator<const T, false> const_iterator;
  120.         typedef cv_iterator<const T, true>  const_reverse_iterator;
  121.  
  122.         const_iterator begin() const
  123.         { return m_pHead; }
  124.         const_iterator end() const
  125.         { return NULL; }
  126.  
  127.         const_reverse_iterator rbegin() const
  128.         { return m_pTail; }
  129.         const_reverse_iterator rend() const
  130.         { return NULL; }
  131.  
  132.         typedef v_iterator<false> iterator;
  133.         typedef v_iterator<true>  reverse_iterator;
  134.  
  135.         iterator begin()
  136.         { return m_pHead; }
  137.         iterator end()
  138.         { return NULL; }
  139.  
  140.         reverse_iterator rbegin()
  141.         { return m_pTail; }
  142.         reverse_iterator rend()
  143.         { return NULL; }
  144.  
  145.         template<class IT>
  146.         struct range_t
  147.         {
  148.                 range_t(IT b)
  149.                         : _begin(b) {}
  150.  
  151.                 IT        begin() const
  152.                 { return _begin; }
  153.                 static IT end()
  154.                 { return NULL; }
  155.  
  156.         protected:
  157.                 IT _begin;
  158.         };
  159.  
  160.         range_t<const_reverse_iterator> reversed() const
  161.         { return rbegin(); }
  162.         range_t<reverse_iterator>       reversed()
  163.         { return rbegin(); }
  164.  
  165.         //
  166.         // Add elements
  167.         //
  168.         void* push_back_new() CRY_FUNCTION_CONTAINS_UNDEFINED_BEHAVIOR
  169.         {
  170.                 void* pNode = allocate();
  171.                 if (pNode)
  172.                 {
  173. #if CRY_UBSAN
  174.                         memset(pNode, 0, sizeof(Node));
  175. #endif
  176.                         insert(NULL, static_cast<Node*>(pNode)); // UBSAN: Invalid cast
  177.                 }
  178.                 return pNode;
  179.         }
  180.         T* push_back()
  181.         {
  182.                 T* pNode = ::new(allocate())T();
  183.                 if (pNode)
  184.                 {
  185.                         insert(NULL, get_node(pNode));
  186.                 }
  187.                 return pNode;
  188.         }
  189.         T* push_back(const T& obj)
  190.         {
  191.                 T* pNode = ::new(allocate())T(obj);
  192.                 if (pNode)
  193.                 {
  194.                         insert(NULL, get_node(pNode));
  195.                 }
  196.                 return pNode;
  197.         }
  198.  
  199.         void* push_front_new() CRY_FUNCTION_CONTAINS_UNDEFINED_BEHAVIOR
  200.         {
  201.                 void* pNode = allocate();
  202.                 if (pNode)
  203.                 {
  204. #if CRY_UBSAN
  205.                         memset(pNode, 0, sizeof(Node));
  206. #endif
  207.                         insert(m_pHead, static_cast<Node*>(pNode)); // UBSAN: Invalid cast
  208.                 }
  209.                 return pNode;
  210.         }
  211.         T* push_front()
  212.         {
  213.                 T* pNode = ::new(allocate())T();
  214.                 if (pNode)
  215.                 {
  216.                         insert(m_pHead, get_node(pNode));
  217.                 }
  218.                 return pNode;
  219.         }
  220.         T* push_front(const T& obj)
  221.         {
  222.                 T* pNode = ::new(allocate())T(obj);
  223.                 if (pNode)
  224.                 {
  225.                         insert(m_pHead, get_node(pNode));
  226.                 }
  227.                 return pNode;
  228.         }
  229.  
  230.         void* insert_new(const T* pNext) CRY_FUNCTION_CONTAINS_UNDEFINED_BEHAVIOR
  231.         {
  232.                 void* pNode = allocate();
  233.                 if (pNode)
  234.                 {
  235. #if CRY_UBSAN
  236.                         memset(pNode, 0, sizeof(Node));
  237. #endif
  238.                         insert(get_node(pNext), static_cast<Node*>(pNode)); // UBSAN: Invalid cast
  239.                 }
  240.                 return pNode;
  241.         }
  242.         T* insert(const T* pNext)
  243.         {
  244.                 T* pNode = ::new(allocate())T();
  245.                 if (pNode)
  246.                 {
  247.                         insert(get_node(pNext), get_node(pNode));
  248.                 }
  249.                 return pNode;
  250.         }
  251.         T* insert(const T* pNext, const T& obj)
  252.         {
  253.                 T* pNode = ::new(allocate())T(obj);
  254.                 if (pNode)
  255.                 {
  256.                         insert(get_node(pNext), get_node(pNode));
  257.                 }
  258.                 return pNode;
  259.         }
  260.  
  261.         //
  262.         // Remove elements
  263.         //
  264.         void erase(T* p)
  265.         {
  266.                 assert(p);
  267.                 assert(!empty());
  268.  
  269.                 Node* pNode = get_node(p);
  270.                 remove(pNode);
  271.                 destroy(pNode);
  272.                 validate();
  273.         }
  274.  
  275.         void pop_back()
  276.         {
  277.                 erase(m_pTail);
  278.         }
  279.  
  280.         void pop_front()
  281.         {
  282.                 erase(m_pHead);
  283.         }
  284.  
  285.         void clear()
  286.         {
  287.                 // Destroy all elements, in reverse order
  288.                 for (Node* p = m_pTail; p != NULL; )
  289.                 {
  290.                         Node* pPrev = p->pPrev;
  291.                         destroy(p);
  292.                         p = pPrev;
  293.                 }
  294.                 reset();
  295.         }
  296.  
  297.         //
  298.         // Move element.
  299.         //
  300.         void move(const T* pDestObj, const T* pSrcObj)
  301.         {
  302.                 assert(pDestObj && pSrcObj && pDestObj != pSrcObj);
  303.                 Node* pSrcNode = get_node(pSrcObj);
  304.  
  305.                 remove(pSrcNode);
  306.                 insert(get_node(pDestObj), pSrcNode);
  307.         }
  308.  
  309.         template<class TSizer>
  310.         void GetMemoryUsagePlain(TSizer* pSizer) const
  311.         {
  312.                 pSizer->AddObject(this, size() * sizeof(Node));
  313.         }
  314.  
  315.         template<class TSizer>
  316.         void GetMemoryUsage(TSizer* pSizer) const
  317.         {
  318.                 for (const auto& e : * this)
  319.                 {
  320.                         if (pSizer->AddObject(&e, sizeof(Node)))
  321.                                 e.GetMemoryUsage(pSizer);
  322.                 }
  323.         }
  324.  
  325. protected:
  326.  
  327.         Node*  m_pHead;
  328.         Node*  m_pTail;
  329.         uint32 m_nSize;
  330.  
  331. protected:
  332.  
  333.         void reset()
  334.         {
  335.                 m_pHead = m_pTail = NULL;
  336.                 m_nSize = 0;
  337.         }
  338.  
  339.         static Node* get_node(const T* p)
  340.         {
  341.                 return non_const(alias_cast<const Node*>(p));
  342.         }
  343.  
  344.         void* allocate()
  345.         {
  346.                 void* pNew = ParticleObjectAllocator().Allocate(sizeof(Node));
  347.                 if (pNew)
  348.                         m_nSize++;
  349.                 return pNew;
  350.         }
  351.         void destroy(Node* pNode)
  352.         {
  353.                 assert(pNode);
  354.                 pNode->~Node();
  355.                 ParticleObjectAllocator().Deallocate(pNode, sizeof(Node));
  356.                 m_nSize--;
  357.         }
  358.  
  359.         void insert(Node* pNext, Node* pNode)
  360.         {
  361.                 assert(pNode);
  362.  
  363.                 Node*& pPrev = pNext ? pNext->pPrev : m_pTail;
  364.                 pNode->pPrev = pPrev;
  365.                 pNode->pNext = pNext;
  366.  
  367.                 if (pPrev)
  368.                         pPrev->pNext = pNode;
  369.                 else
  370.                         m_pHead = pNode;
  371.  
  372.                 pPrev = pNode;
  373.  
  374.                 validate();
  375.         }
  376.  
  377.         void remove(Node* pNode)
  378.         {
  379.                 assert(pNode);
  380.                 assert(!empty());
  381.  
  382.                 if (!pNode->pPrev)
  383.                 {
  384.                         assert(pNode == m_pHead);
  385.                         m_pHead = pNode->pNext;
  386.                 }
  387.                 else
  388.                         pNode->pPrev->pNext = pNode->pNext;
  389.  
  390.                 if (!pNode->pNext)
  391.                 {
  392.                         assert(pNode == m_pTail);
  393.                         m_pTail = pNode->pPrev;
  394.                 }
  395.                 else
  396.                         pNode->pNext->pPrev = pNode->pPrev;
  397.         }
  398.  
  399.         void validate() const
  400.         {
  401. #if defined(_DEBUG)
  402.                 if (empty())
  403.                 {
  404.                         assert(!m_nSize && !m_pHead && !m_pTail);
  405.                 }
  406.                 else
  407.                 {
  408.                         assert(m_pHead && !m_pHead->pPrev);
  409.                         assert(m_pTail && !m_pTail->pNext);
  410.                         if (m_nSize == 1)
  411.                                 assert(m_pHead == m_pTail);
  412.                 }
  413.  
  414.                 Node* pPrev = NULL;
  415.                 int nCount = 0;
  416.                 for (Node* p = m_pHead; p; p = p->pNext)
  417.                 {
  418.                         assert(p->pPrev == pPrev);
  419.                         assert(p->pNext || p == m_pTail);
  420.                         pPrev = p;
  421.                         nCount++;
  422.                 }
  423.                 assert(nCount == size());
  424. #endif // _DEBUG
  425.         }
  426. };
  427.  
  428. #endif // _CRY_PARTICLE_LIST_H_
  429.  
downloadParticleList.h Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top