| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- // -----------------------------------------------------------------------------------------------------------------------------
- // ContinuousPageStack declaration
- // -----------------------------------------------------------------------------------------------------------------------------
- template<const size_t InitialPageCount = 1>
- class ContinuousPageStack : protected Allocator
- {
- protected:
- class Iterator
- {
- protected:
- size_t nextTop;
- protected:
- inline Iterator(const ContinuousPageStack &stack);
- public:
- inline size_t Position() const;
- inline operator bool() const;
- };
- friend class Iterator;
- private:
- PageAllocator *const pageAllocator;
- PageAllocation *pageAllocation;
- size_t bufferSize;
- protected:
- size_t nextTop;
- protected:
- inline ContinuousPageStack(PageAllocator *const pageAllocator, void (*const outOfMemoryFunc)());
- ~ContinuousPageStack();
- inline char *Buffer() const;
- public:
- inline bool IsEmpty() const;
- inline void Clear();
- inline size_t Position() const;
- inline char* Push(const size_t size);
- inline char* Top(const size_t size) const;
- inline char* Pop(const size_t size);
- inline void UnPop(const size_t size);
- inline void PopTo(const size_t position);
- private:
- void Resize(size_t requestedSize);
- };
- // -----------------------------------------------------------------------------------------------------------------------------
- // ContinuousPageStackOfFixedElements declaration
- // -----------------------------------------------------------------------------------------------------------------------------
- template<class T, const size_t InitialPageCount = 1>
- class ContinuousPageStackOfFixedElements : public ContinuousPageStack<InitialPageCount>
- {
- public:
- class Iterator : public ContinuousPageStack<InitialPageCount>::Iterator
- {
- private:
- const ContinuousPageStackOfFixedElements &stack;
- public:
- inline Iterator(const ContinuousPageStackOfFixedElements &stack);
- inline T &operator *() const;
- inline T *operator ->() const;
- inline Iterator &operator ++(); // pre-increment
- inline Iterator operator ++(int); // post-increment
- };
- friend class Iterator;
- public:
- inline ContinuousPageStackOfFixedElements(PageAllocator *const pageAllocator, void (*const outOfMemoryFunc)());
- public:
- inline char* Push();
- inline T* Top() const;
- inline T* Pop();
- inline void UnPop();
- inline void PopTo(const size_t position);
- };
- // -----------------------------------------------------------------------------------------------------------------------------
- // ContinuousPageStackOfVariableElements declaration
- // -----------------------------------------------------------------------------------------------------------------------------
- template<class T, const size_t InitialPageCount = 1>
- class ContinuousPageStackOfVariableElements : public ContinuousPageStack<InitialPageCount>
- {
- public:
- class Iterator : public ContinuousPageStack<InitialPageCount>::Iterator
- {
- private:
- size_t topElementSize;
- const ContinuousPageStackOfVariableElements &stack;
- public:
- inline Iterator(const ContinuousPageStackOfVariableElements &stack);
- inline T &operator *() const;
- inline T *operator ->() const;
- inline Iterator &operator ++(); // pre-increment
- inline Iterator operator ++(int); // post-increment
- };
- friend class Iterator;
- private:
- class VariableElement
- {
- private:
- const size_t previousElementSize;
- char data[0];
- public:
- inline VariableElement(const size_t previousElementSize);
- public:
- template<class ActualT> inline static size_t Size();
- inline size_t PreviousElementSize() const;
- inline char *Data();
- };
- private:
- size_t topElementSize;
- public:
- inline ContinuousPageStackOfVariableElements(PageAllocator *const pageAllocator, void (*const outOfMemoryFunc)());
- public:
- template<class ActualT> inline char* Push();
- inline T* Top() const;
- inline T* Pop();
- template<class ActualT> inline void UnPop();
- inline void PopTo(const size_t position);
- };
- // -----------------------------------------------------------------------------------------------------------------------------
- // ContinuousPageStack definition
- // -----------------------------------------------------------------------------------------------------------------------------
- // --------
- // Iterator
- // --------
- template<const size_t InitialPageCount>
- inline ContinuousPageStack<InitialPageCount>::Iterator::Iterator(const ContinuousPageStack &stack)
- : nextTop(stack.nextTop)
- {
- }
- template<const size_t InitialPageCount>
- inline size_t ContinuousPageStack<InitialPageCount>::Iterator::Position() const
- {
- return nextTop;
- }
- template<const size_t InitialPageCount>
- inline ContinuousPageStack<InitialPageCount>::Iterator::operator bool() const
- {
- return nextTop != 0;
- }
- // -------------------
- // ContinuousPageStack
- // -------------------
- template<const size_t InitialPageCount>
- inline ContinuousPageStack<InitialPageCount>::ContinuousPageStack(
- PageAllocator *const pageAllocator,
- void (*const outOfMemoryFunc)())
- : Allocator(outOfMemoryFunc), pageAllocator(pageAllocator), bufferSize(0), nextTop(0)
- {
- Assert(pageAllocator);
- }
- template<const size_t InitialPageCount>
- ContinuousPageStack<InitialPageCount>::~ContinuousPageStack()
- {
- if(bufferSize && !pageAllocator->IsClosed())
- pageAllocator->ReleaseAllocation(pageAllocation);
- }
- template<const size_t InitialPageCount>
- inline char *ContinuousPageStack<InitialPageCount>::Buffer() const
- {
- Assert(bufferSize);
- return pageAllocation->GetAddress();
- }
- template<const size_t InitialPageCount>
- inline bool ContinuousPageStack<InitialPageCount>::IsEmpty() const
- {
- return nextTop == 0;
- }
- template<const size_t InitialPageCount>
- inline void ContinuousPageStack<InitialPageCount>::Clear()
- {
- nextTop = 0;
- }
- template<const size_t InitialPageCount>
- inline size_t ContinuousPageStack<InitialPageCount>::Position() const
- {
- return nextTop;
- }
- template<const size_t InitialPageCount>
- inline char* ContinuousPageStack<InitialPageCount>::Push(const size_t size)
- {
- Assert(size);
- if(bufferSize - nextTop < size)
- Resize(size);
- char* const res = Buffer() + nextTop;
- nextTop += size;
- return res;
- }
- template<const size_t InitialPageCount>
- inline char* ContinuousPageStack<InitialPageCount>::Top(const size_t size) const
- {
- if (nextTop == 0)
- return 0;
- else
- {
- Assert(size != 0);
- Assert(size <= nextTop);
- return Buffer() + (nextTop - size);
- }
- }
- template<const size_t InitialPageCount>
- inline char* ContinuousPageStack<InitialPageCount>::Pop(const size_t size)
- {
- if (nextTop == 0)
- return 0;
- else
- {
- Assert(size != 0);
- Assert(nextTop >= size);
- nextTop -= size;
- return Buffer() + nextTop;
- }
- }
- template<const size_t InitialPageCount>
- inline void ContinuousPageStack<InitialPageCount>::UnPop(const size_t size)
- {
- Assert(size != 0);
- Assert(nextTop + size <= bufferSize);
- nextTop += size;
- }
- template<const size_t InitialPageCount>
- void ContinuousPageStack<InitialPageCount>::Resize(size_t requestedSize)
- {
- Assert(requestedSize);
- Assert(requestedSize <= InitialPageCount * AutoSystemInfo::PageSize);
- if(!bufferSize)
- {
- pageAllocation = pageAllocator->AllocAllocation(InitialPageCount);
- if (!pageAllocation)
- {
- outOfMemoryFunc();
- AnalysisAssert(false);
- }
- bufferSize = pageAllocation->GetSize();
- return;
- }
- PageAllocation *const newPageAllocation = pageAllocator->AllocAllocation(pageAllocation->GetPageCount() * 2);
- if (!newPageAllocation)
- {
- outOfMemoryFunc();
- AnalysisAssert(false);
- }
- js_memcpy_s(newPageAllocation->GetAddress(), newPageAllocation->GetSize(), Buffer(), nextTop);
- pageAllocator->ReleaseAllocation(pageAllocation);
- pageAllocation = newPageAllocation;
- bufferSize = newPageAllocation->GetSize();
- }
- template<const size_t InitialPageCount>
- inline void ContinuousPageStack<InitialPageCount>::PopTo(const size_t position)
- {
- Assert(position <= nextTop);
- nextTop = position;
- }
- // -----------------------------------------------------------------------------------------------------------------------------
- // ContinuousPageStackOfFixedElements definition
- // -----------------------------------------------------------------------------------------------------------------------------
- // --------
- // Iterator
- // --------
- template<class T, const size_t InitialPageCount>
- inline ContinuousPageStackOfFixedElements<T, InitialPageCount>::Iterator::Iterator(
- const ContinuousPageStackOfFixedElements &stack)
- : ContinuousPageStack<InitialPageCount>::Iterator(stack), stack(stack)
- {
- }
- template<class T, const size_t InitialPageCount>
- inline T &ContinuousPageStackOfFixedElements<T, InitialPageCount>::Iterator::operator *() const
- {
- Assert(*this);
- Assert(this->nextTop <= stack.nextTop);
- return *reinterpret_cast<T *>(&stack.Buffer()[this->nextTop - sizeof(T)]);
- }
- template<class T, const size_t InitialPageCount>
- inline T *ContinuousPageStackOfFixedElements<T, InitialPageCount>::Iterator::operator ->() const
- {
- return &**this;
- }
- template<class T, const size_t InitialPageCount>
- inline typename ContinuousPageStackOfFixedElements<T, InitialPageCount>::Iterator &ContinuousPageStackOfFixedElements<T, InitialPageCount>::Iterator::operator ++() // pre-increment
- {
- Assert(*this);
- this->nextTop -= sizeof(T);
- return *this;
- }
- template<class T, const size_t InitialPageCount>
- inline typename ContinuousPageStackOfFixedElements<T, InitialPageCount>::Iterator ContinuousPageStackOfFixedElements<T, InitialPageCount>::Iterator::operator ++(int) // post-increment
- {
- Iterator it(*this);
- ++*this;
- return it;
- }
- // ----------------------------------
- // ContinuousPageStackOfFixedElements
- // ----------------------------------
- template<class T, const size_t InitialPageCount>
- inline ContinuousPageStackOfFixedElements<T, InitialPageCount>::ContinuousPageStackOfFixedElements(
- PageAllocator *const pageAllocator,
- void (*const outOfMemoryFunc)())
- : ContinuousPageStack<InitialPageCount>(pageAllocator, outOfMemoryFunc)
- {
- }
- template<class T, const size_t InitialPageCount>
- inline char* ContinuousPageStackOfFixedElements<T, InitialPageCount>::Push()
- {
- return ContinuousPageStack<InitialPageCount>::Push(sizeof(T));
- }
- template<class T, const size_t InitialPageCount>
- inline T* ContinuousPageStackOfFixedElements<T, InitialPageCount>::Top() const
- {
- return reinterpret_cast<T*>(ContinuousPageStack<InitialPageCount>::Top(sizeof(T)));
- }
- template<class T, const size_t InitialPageCount>
- inline T* ContinuousPageStackOfFixedElements<T, InitialPageCount>::Pop()
- {
- return reinterpret_cast<T*>(ContinuousPageStack<InitialPageCount>::Pop(sizeof(T)));
- }
- template<class T, const size_t InitialPageCount>
- inline void ContinuousPageStackOfFixedElements<T, InitialPageCount>::UnPop()
- {
- return ContinuousPageStack<InitialPageCount>::UnPop(sizeof(T));
- }
- template<class T, const size_t InitialPageCount>
- inline void ContinuousPageStackOfFixedElements<T, InitialPageCount>::PopTo(const size_t position)
- {
- ContinuousPageStack<InitialPageCount>::PopTo(position);
- }
- // -----------------------------------------------------------------------------------------------------------------------------
- // ContinuousPageStackOfVariableElements definition
- // -----------------------------------------------------------------------------------------------------------------------------
- // --------
- // Iterator
- // --------
- template<class T, const size_t InitialPageCount>
- inline ContinuousPageStackOfVariableElements<T, InitialPageCount>::Iterator::Iterator(
- const ContinuousPageStackOfVariableElements &stack)
- : ContinuousPageStack<InitialPageCount>::Iterator(stack), topElementSize(stack.topElementSize), stack(stack)
- {
- }
- template<class T, const size_t InitialPageCount>
- inline T &ContinuousPageStackOfVariableElements<T, InitialPageCount>::Iterator::operator *() const
- {
- Assert(*this);
- Assert(this->nextTop <= stack.nextTop);
- return *reinterpret_cast<T*>(reinterpret_cast<VariableElement *>(&stack.Buffer()[this->nextTop - this->topElementSize])->Data());
- }
- template<class T, const size_t InitialPageCount>
- inline T *ContinuousPageStackOfVariableElements<T, InitialPageCount>::Iterator::operator ->() const
- {
- return &**this;
- }
- template<class T, const size_t InitialPageCount>
- inline typename ContinuousPageStackOfVariableElements<T, InitialPageCount>::Iterator &ContinuousPageStackOfVariableElements<T, InitialPageCount>::Iterator::operator ++() // pre-increment
- {
- Assert(*this);
- Assert(this->nextTop <= stack.nextTop);
- topElementSize = reinterpret_cast<VariableElement *>(&stack.Buffer()[this->nextTop -= this->topElementSize])->PreviousElementSize();
- return *this;
- }
- template<class T, const size_t InitialPageCount>
- inline typename ContinuousPageStackOfVariableElements<T, InitialPageCount>::Iterator ContinuousPageStackOfVariableElements<T, InitialPageCount>::Iterator::operator ++(int) // post-increment
- {
- Iterator it(*this);
- ++*this;
- return it;
- }
- // ---------------
- // VariableElement
- // ---------------
- template<class T, const size_t InitialPageCount>
- inline ContinuousPageStackOfVariableElements<T, InitialPageCount>::VariableElement::VariableElement(
- const size_t previousElementSize)
- : previousElementSize(previousElementSize)
- {
- }
- template<class T, const size_t InitialPageCount>
- template<class ActualT>
- inline size_t ContinuousPageStackOfVariableElements<T, InitialPageCount>::VariableElement::Size()
- {
- return sizeof(VariableElement) + sizeof(ActualT);
- }
- template<class T, const size_t InitialPageCount>
- inline size_t ContinuousPageStackOfVariableElements<T, InitialPageCount>::VariableElement::PreviousElementSize() const
- {
- return previousElementSize;
- }
- template<class T, const size_t InitialPageCount>
- inline char* ContinuousPageStackOfVariableElements<T, InitialPageCount>::VariableElement::Data()
- {
- return data;
- }
- // -------------------------------------
- // ContinuousPageStackOfVariableElements
- // -------------------------------------
- template<class T, const size_t InitialPageCount>
- inline ContinuousPageStackOfVariableElements<T, InitialPageCount>::ContinuousPageStackOfVariableElements(
- PageAllocator *const pageAllocator,
- void (*const outOfMemoryFunc)())
- : ContinuousPageStack<InitialPageCount>(pageAllocator, outOfMemoryFunc)
- {
- }
- template<class T, const size_t InitialPageCount>
- template<class ActualT>
- inline char* ContinuousPageStackOfVariableElements<T, InitialPageCount>::Push()
- {
- TemplateParameter::SameOrDerivedFrom<ActualT, T>(); // ActualT must be the same type as, or a type derived from, T
- VariableElement *const element =
- new(ContinuousPageStack<InitialPageCount>::Push(VariableElement::template
- Size<ActualT>())) VariableElement(topElementSize);
- topElementSize = VariableElement::template Size<ActualT>();
- return element->Data();
- }
- template<class T, const size_t InitialPageCount>
- inline T* ContinuousPageStackOfVariableElements<T, InitialPageCount>::Top() const
- {
- VariableElement* const element = reinterpret_cast<VariableElement*>(ContinuousPageStack<InitialPageCount>::Top(topElementSize));
- return element == 0 ? 0 : reinterpret_cast<T*>(element->Data());
- }
- template<class T, const size_t InitialPageCount>
- inline T* ContinuousPageStackOfVariableElements<T, InitialPageCount>::Pop()
- {
- VariableElement *const element = reinterpret_cast<VariableElement*>(ContinuousPageStack<InitialPageCount>::Pop(topElementSize));
- if (element == 0)
- return 0;
- else
- {
- topElementSize = element->PreviousElementSize();
- return reinterpret_cast<T*>(element->Data());
- }
- }
- template<class T, const size_t InitialPageCount>
- template<class ActualT>
- inline void ContinuousPageStackOfVariableElements<T, InitialPageCount>::UnPop()
- {
- TemplateParameter::SameOrDerivedFrom<ActualT, T>(); // ActualT must be the same type as, or a type derived from, T
- ContinuousPageStack<InitialPageCount>::UnPop(VariableElement::template
- Size<ActualT>());
- Assert(reinterpret_cast<VariableElement*>(ContinuousPageStack<InitialPageCount>::Top(VariableElement::template
- Size<ActualT>()))->PreviousElementSize() == topElementSize);
- topElementSize = VariableElement::template Size<ActualT>();
- }
- template<class T, const size_t InitialPageCount>
- inline void ContinuousPageStackOfVariableElements<T, InitialPageCount>::PopTo(const size_t position)
- {
- Assert(position <= this->nextTop);
- if(position != this->nextTop)
- {
- Assert(position + sizeof(VariableElement) <= this->nextTop);
- topElementSize = reinterpret_cast<VariableElement *>(&this->Buffer()[position])->PreviousElementSize();
- }
- ContinuousPageStack<InitialPageCount>::PopTo(position);
- }
|