123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- /*
- * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
- * its licensors.
- *
- * For complete copyright and license terms please see the LICENSE at the root of this
- * distribution (the "License"). All use of this software is governed by the License,
- * or, if provided, by the license below or the license accompanying this file. Do not
- * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *
- */
- // Original file Copyright Crytek GMBH or its affiliates, used under license.
- #ifndef CRYINCLUDE_CRY3DENGINE_3DENGINEMEMORY_H
- #define CRYINCLUDE_CRY3DENGINE_3DENGINEMEMORY_H
- #pragma once
- // The type of pool responsible for temporary allocations within the 3dengine
- //
- // Note: The header is included here for reasons of devirtualization. If
- // included directly from the precompiled header in 3dEngine, the gamedll will
- // fail to compile!
- #include <CryPool/PoolAlloc.h>
- #include <InplaceFactory.h>
- using NCryPoolAlloc::CFirstFit; // speed of allocations are crucial, so simply use the first fitting free allocation
- using NCryPoolAlloc::CInPlace; //
- using NCryPoolAlloc::CMemoryDynamic; // the pool itself will be dynamically allocated
- using NCryPoolAlloc::CListItemInPlace; // use inplace items
- // Tempororary Pool Holder
- class CTemporaryPool
- {
- private:
- // Access granted for 3dEngine to create, destroy and maintain the temporary
- // pool for the 3d engine
- friend class C3DEngine;
- // The static pool instance - one pool to rule them all (temp allocations at least)
- static CTemporaryPool* s_Instance;
- // The type of the backing temporary pool
- typedef CFirstFit<CInPlace<CMemoryDynamic>, CListItemInPlace> TTemporaryPool;
- TTemporaryPool Pool;
- // A non-recursive critical section guards the pool against concurrent access
- typedef CryCriticalSectionNonRecursive TTemporaryPoolLock;
- TTemporaryPoolLock Lock;
- // Initialize the pool manager.
- //
- // Allocates the backing storage and initializes the temporary pool
- // itself. The backing storage is aligned to 16 bytes to reduce the amount of
- // cachelines crossed by the temporary pool
- static bool Initialize(size_t poolSize)
- {
- // Create the object instance
- s_Instance = new CTemporaryPool();
- if (!s_Instance)
- {
- CryFatalError("CTemporaryPool::Init(): could not create an instance of CTemporaryPool");
- return false;
- }
- // Allocate the backing storage
- uint8* tempPool = reinterpret_cast<uint8*>(CryModuleMemalign(poolSize, 16));
- if (!tempPool)
- {
- CryFatalError("CTemporaryPool::Init(): could not allocate %" PRISIZE_T " bytes for temportary pool", poolSize);
- return false;
- }
- // Initialize the actual pool
- s_Instance->Pool.InitMem(poolSize, tempPool);
- return true;
- }
- // Shutdown the temporary pool manager.
- //
- // Frees the temporary pool
- static bool Shutdown()
- {
- if (s_Instance == NULL)
- {
- CryFatalError("CTemporaryPool::Shutdown(): no temporary pool instance present");
- return false;
- }
- bool error = false;
- CTemporaryPool& instance = *s_Instance;
- if (instance.Pool.Data())
- {
- CryModuleMemalignFree(instance.Pool.Data());
- }
- else
- {
- error = true;
- }
- delete s_Instance;
- s_Instance = NULL;
- return !error;
- }
- // Templated construct helper member function using an inplace factory
- //
- // Called from the templated New<T, Expr> function below. Returns a typed
- // pointer to the inplace constructed object.
- template<typename T, typename InPlaceFactory>
- T* Construct(const InPlaceFactory& factory, void* storage)
- {
- return reinterpret_cast<T*>(factory.template apply<T>(storage));
- }
- // Templated destruct helper member function.
- //
- // Calls the object's destructor and returns a void pointer to the storage
- template<typename T>
- void* Destruct(T* obj)
- {
- obj->~T();
- return reinterpret_cast<void*>(obj);
- }
- // Empty private constructor/destructors to prevent clients from creating and
- // destroying instances of CTemporaryPool (there should only be one instance
- // in the 3DEngine).
- CTemporaryPool() {};
- ~CTemporaryPool() {};
- public:
- // Allocate a block of memory with the given size and alignment
- void* Allocate(size_t size, size_t align)
- {
- AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
- void* pData = Pool.Allocate<void*>(size, align);
- if (pData == NULL)
- {
- CryFatalError("**** could not allocate %" PRISIZE_T " bytes from temporary pool", size);
- }
- return Pool.Resolve<void*>(pData);
- };
- // Allocates memory and constructs object of type 'T'
- //
- // Note: This method is respects the alignment of 'T' via C99 alignof()
- template<typename T, typename Expr>
- T* New(const Expr& expr)
- {
- AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
- void* pObjStorage = Pool.Allocate<void*>(sizeof(T), alignof(T));
- if (pObjStorage == NULL)
- {
- CryFatalError("**** could not allocate %d bytes from temporary pool",
- (int)sizeof (T));
- }
- return Construct<T>(expr, pObjStorage);
- };
- // Allocates memory and constructs object of type 'T'
- //
- // Note: This method is respects the alignment of 'T' via C99 alignof()
- template<typename T>
- T* New()
- {
- AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
- void* pObjStorage = Pool.Allocate<void*>(sizeof(T), alignof(T));
- if (pObjStorage == NULL)
- {
- CryFatalError("**** could not allocate %d bytes from temporary pool",
- (int)sizeof (T));
- }
- return Construct<T>(InplaceFactory(), pObjStorage);
- };
- // Frees a block of memory from the temporary pool
- //
- void Free(void* ptr)
- {
- AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
- Pool.Free(ptr);
- }
- // Destroys an object of type 'T' and frees the underlying block of memory
- template<typename T>
- void Delete(T* ptr)
- {
- AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
- Pool.Free(Destruct<T>(ptr));
- }
- // Static function to retrieve the static instance of CTemporaryPool
- static CTemporaryPool* Get() { return s_Instance; };
- void GetMemoryUsage(ICrySizer* pSizer) const
- {
- pSizer->AddObject(Pool.Data(), Pool.MemSize());
- }
- };
- // A stl compliant scratch allocator that uses the given temporary pool.
- template <class Type>
- class scratch_allocator
- {
- public:
- typedef Type value_type;
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- template <class value_type1>
- struct rebind
- {
- typedef scratch_allocator<value_type1> other;
- };
- scratch_allocator() {}
- template <class value_type1>
- scratch_allocator(const scratch_allocator<value_type1>&) {}
- scratch_allocator(const scratch_allocator<value_type>&) {}
- ~scratch_allocator() {}
- pointer address(reference x) const {return &x; }
- const_pointer address(const_reference x) const { return &x; }
- // Note: size can be zero - return value will be null in that case
- value_type* allocate(size_type n, const void* = 0)
- {
- if (n != 0)
- {
- size_type buf_size = n * sizeof(value_type);
- void* ret = CTemporaryPool::Get()->Allocate(
- buf_size,
- alignof(value_type));
- return reinterpret_cast<value_type*>(ret);
- }
- return 0;
- }
- // Note: size can be zero.
- void deallocate(pointer p, [[maybe_unused]] size_type n)
- {
- if (p != NULL)
- {
- CTemporaryPool::Get()->Free(p);
- }
- }
- size_type max_size() const { return size_t(-1) / sizeof(value_type); }
- void construct(pointer p, const_reference val)
- { new (reinterpret_cast<void*>(p))value_type(val); }
- void destroy(pointer p) { p->~value_type(); }
- void cleanup() {}
- size_t get_heap_size() { return 0; }
- size_t get_wasted_in_allocation() { return 0; }
- size_t get_wasted_in_blocks() { return 0; }
- };
- // A scratch vector type to use the stl vector
- template<typename Type>
- class scratch_vector
- : public std::vector<Type, scratch_allocator<Type> >
- {
- };
- namespace util
- {
- extern void* pool_allocate(size_t nSize);
- extern void pool_free(void* ptr);
- }
- #endif // CRYINCLUDE_CRY3DENGINE_3DENGINEMEMORY_H
|