| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- ///////////////////////////////////////////////////////////////////////////////
- // Copyright (c) Electronic Arts Inc. All rights reserved.
- ///////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- // This is a small templated list implementation which suffices for our
- // purposes but is not optimal. It is present in order to avoid dependencies
- // on external libraries.
- /////////////////////////////////////////////////////////////////////////////
- #ifndef EATHREAD_EATHREAD_LIST_H
- #define EATHREAD_EATHREAD_LIST_H
- #include <eathread/internal/config.h>
- #include <eathread/eathread.h>
- #include <stddef.h> // size_t, etc.
- #include <new>
- #if defined(EA_PRAGMA_ONCE_SUPPORTED)
- #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
- #endif
- namespace EA
- {
- namespace Thread
- {
- namespace details
- {
- /// Default allocator implementation used by the simple_list class
- template<typename T>
- struct ListDefaultAllocatorImpl
- {
- template<typename OT>
- struct rebind { typedef ListDefaultAllocatorImpl<OT> other; };
- T* construct()
- {
- Allocator* pAllocator = GetAllocator();
- if(pAllocator)
- return new(pAllocator->Alloc(sizeof(T))) T;
- else
- return new T;
- }
- void destroy(T* obj)
- {
- Allocator* pAllocator = GetAllocator();
- if(pAllocator)
- {
- obj->~T();
- pAllocator->Free(obj);
- }
- else
- delete obj;
- }
- };
- }
- /// Simple version of an STL bidirectional list.
- /// Implemented to avoid dependency on container implementations.
- ///
- /// This implementation has some non-stl standard methods like find.
- ///
- template<typename T, class Allocator = details::ListDefaultAllocatorImpl<T> >
- class simple_list
- {
- simple_list(const simple_list&);
- simple_list& operator=(const simple_list&);
- protected:
- struct list_node
- {
- T mValue;
- list_node* mpPrev;
- list_node* mpNext;
- };
- typedef list_node node_t;
- typedef typename Allocator::template rebind<list_node>::other allocator_t;
-
- allocator_t mAllocator;
- node_t* mpNodeHead;
- node_t* mpNodeTail;
- size_t mnSize;
- public:
- typedef T value_type; //< list value type
- typedef const T const_value_type; //< constant list value type
- typedef const T& const_value_ref_type; //< constant reference list value type
-
- struct const_iterator;
- struct iterator;
- friend struct const_iterator;
- friend struct iterator;
- struct const_iterator
- {
- friend class simple_list<T>;
- const_iterator()
- : mpNode(NULL)
- { }
- const_iterator(const const_iterator& rhs)
- : mpNode(rhs.mpNode)
- { }
- const_iterator& operator=(const const_iterator& rhs)
- {
- mpNode = rhs.mpNode;
- return *this;
- }
- const T& operator*() const
- { return mpNode->mValue; }
- const T* operator->() const
- { return &**this; }
-
- bool operator==(const const_iterator& rhs) const
- { return rhs.mpNode == mpNode; }
- bool operator!=(const const_iterator& rhs) const
- { return rhs.mpNode != mpNode; }
- const_iterator& operator++()
- {
- mpNode = mpNode->mpNext;
- return *this;
- }
- protected:
- const node_t* mpNode;
- protected:
- const_iterator(node_t* pNode)
- : mpNode(pNode)
- { }
- const_iterator& operator=(const node_t* pNode)
- {
- mpNode = pNode;
- return *this;
- }
- }; // const_iterator
- struct iterator : public const_iterator
- {
- friend class simple_list<T>;
- iterator()
- : const_iterator(){ }
- iterator(const const_iterator& rhs)
- : const_iterator(rhs)
- { }
- iterator& operator=(const const_iterator& rhs)
- {
- *static_cast<const_iterator*>(this)= rhs;
- return *this;
- }
- T& operator*() const
- { return const_cast<T&>(**static_cast<const const_iterator*>(this)); }
- T& operator->() const
- { return const_cast<T*>(&**static_cast<const const_iterator*>(this)); }
- iterator& operator++()
- {
- ++(*static_cast<const_iterator*>(this));
- return *this;
- }
- protected:
- iterator(node_t* pNode)
- : const_iterator(pNode)
- { }
- iterator& operator=(node_t* pNode)
- {
- const_cast<node_t*>(*this) = pNode;
- return *this;
- }
- }; // iterator
- simple_list()
- : mnSize(0)
- {
- mpNodeHead = mAllocator.construct();
- mpNodeTail = mAllocator.construct();
- mpNodeHead->mpNext = mpNodeTail;
- mpNodeHead->mpPrev = mpNodeTail;
- mpNodeTail->mpNext = mpNodeHead;
- mpNodeTail->mpPrev = mpNodeHead;
- }
- ~simple_list()
- {
- clear();
- mAllocator.destroy(mpNodeHead);
- mAllocator.destroy(mpNodeTail);
- }
- bool empty() const
- { return mpNodeHead->mpNext == mpNodeTail; }
- void push_back(const T& value)
- {
- node_t* const pNode = mAllocator.construct();
- pNode->mValue = value;
- pNode->mpPrev = mpNodeTail->mpPrev;
- pNode->mpNext = mpNodeTail;
- pNode->mpPrev->mpNext = pNode;
- mpNodeTail->mpPrev = pNode;
- ++mnSize;
- }
- void push_front(const T& value)
- {
- node_t* const pNode = mAllocator.construct();
- pNode->mValue = value;
- pNode->mpPrev = mpNodeHead;
- pNode->mpNext = mpNodeHead->mpNext;
- mpNodeHead->mpNext = pNode;
- ++mnSize;
- }
- void pop_front()
- {
- if(!empty())
- {
- node_t* const pNode = mpNodeHead->mpNext;
- mpNodeHead->mpNext = pNode->mpNext;
- pNode->mpNext->mpPrev = mpNodeHead;
- mAllocator.destroy(pNode);
- --mnSize;
- }
- }
- size_t size() const
- { return mnSize; }
- iterator erase(iterator& iter)
- {
- if(!empty())
- {
- node_t* const pNext = iter.mpNode->mpNext;
- iter.mpNode->mpNext->mpPrev = iter.mpNode->mpPrev;
- iter.mpNode->mpPrev->mpNext = iter.mpNode->mpNext;
- --mnSize;
- mAllocator.destroy(const_cast<node_t*>(iter.mpNode));
- return pNext;
- }
- return end();
- }
- void clear()
- {
- if(!empty())
- {
- node_t* pNode = mpNodeHead->mpNext;
- while(pNode != mpNodeTail)
- {
- node_t* const pNext = pNode->mpNext;
- pNode->mpNext->mpPrev = pNode->mpPrev;
- pNode->mpPrev->mpNext = pNext;
- mAllocator.destroy(pNode);
- pNode = pNext;
- }
- mnSize = 0;
- }
- }
- T& front() const
- { return mpNodeHead->mpNext->mValue; }
- const const_iterator begin() const
- { return mpNodeHead->mpNext; }
- const const_iterator end() const
- { return mpNodeTail; }
- /// returns end()if not found
- iterator find(const T& element)
- {
- iterator iter = begin();
- while((iter != end()) && !(element == *iter))
- ++iter;
- return iter;
- }
- }; // simple_list
- } // namespace Thread
- } // namespace EA
- #endif // EATHREAD_EATHREAD_LIST_H
|