/*---------------------------------------------------------------------------* Project: Horizon File: fnd_UnitHeap.h Copyright (C)2009 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 16565 $ *---------------------------------------------------------------------------*/ #ifndef NN_FND_FND_WAITABLEUNITHEAP_H_ #define NN_FND_FND_WAITABLEUNITHEAP_H_ #include #include #ifdef __cplusplus namespace nn { namespace fnd { // not documented // 未テスト template , class Semaphore = nn::os::LightSemaphore> class WaitableUnitHeap : private UnitHeapTemplate { private: typedef UnitHeapTemplate Base; Semaphore m_Semaphore; public: using Base::GetRequiredHeapSize; WaitableUnitHeap() {} WaitableUnitHeap(size_t unit, uptr addr, size_t size, s32 alignment = Base::DEFAULT_ALIGNMENT, bit32 option = 0) { Initialize(unit, addr, size, alignment, option); } template explicit WaitableUnitHeap(size_t unit, const MemoryBlock& block, s32 alignment = Base::DEFAULT_ALIGNMENT, bit32 option = 0) { Initialize(unit, block.GetAddress(), block.GetSize(), alignment, option); } void Initialize(size_t unit, uptr addr, size_t size, s32 alignment = Base::DEFAULT_ALIGNMENT, bit32 option = 0) { Base::Initialize(unit, addr, size, alignment, option); s32 maxCount = Base::GetTotalSize() / Base::GetUnitSize(); this->m_Semaphore.Initialize(maxCount, maxCount); } using Base::Invalidate; /*! @brief 終了処理 */ void Finalize() { m_Semaphore.Finalize(); Base::Finalize(); } /*! @brief ヒープからユニットに基づいてメモリを確保します。 @return メモリへのポインタを返します。確保できるメモリがない場合は 0 を返します。 */ void* TryAllocate() { if (m_Semaphore.TryAcquire()) { void* ret = Base::Allocate(); NN_TASSERT_(ret); return ret; } else { return 0; } } /*! @brief ヒープからユニットに基づいてメモリを確保します。 確保できるメモリがない場合は、確保できるようになるまで待機します。 @return メモリへのポインタを返します。 */ void* Allocate() { m_Semaphore.Acquire(); void* ret = Base::Allocate(); NN_TASSERT_(ret); return ret; } /*! @brief ヒープにメモリを解放します。 @param[in] p 解放するメモリへのポインタ */ void Free(void* p) { Base::Free(p); m_Semaphore.Release(); } /*! @brief このヒープから確保したメモリを解放します。 仮想メンバ関数であるため、HeapBaseから解放できます。 @param[in] p メモリへのポインタを指定します。 */ virtual void FreeV(void* p) { Free(p); } using Base::GetUnitSize; using Base::GetAllocatableCount; /*! @brief ユニットヒープのメモリ領域の開始アドレスを取得します。 @return ユニットヒープのメモリ領域の開始アドレスをを返します。 */ virtual void* GetStartAddress() const { return Base::GetStartAddress(); } /*! @brief ユニットヒープに割り当てられているメモリサイズを取得します。 @return ユニットヒープに割り当てられているメモリサイズを返します。 */ virtual size_t GetTotalSize() const { return Base::GetTotalSize(); } /*! @brief ヒープ内部の情報を表示します。(デバッグ用) */ virtual void Dump() const { Base::Dump(); } /*! @brief 指定したアドレスがヒープに含まれているか調べます。 @param[in] addr 調べたいアドレスを指定します。 @return ヒープに含まれていれば true を返し、含まれていなければ false を返します。 */ virtual bool HasAddress(const void* addr) const { return Base::HasAddress(addr); } class Allocator; }; template class WaitableUnitHeap::Allocator : public IAllocator { public: Allocator(WaitableUnitHeap& heap) : m_Heap(&heap) {} Allocator() : m_Heap(0) {} void Initialize(WaitableUnitHeap& heap) { m_Heap = &heap; } WaitableUnitHeap* GetHeap() { return m_Heap; } const WaitableUnitHeap* GetHeap() const { return m_Heap; } virtual void* Allocate(size_t size, s32 alignment); virtual void Free(void* p) { m_Heap->Free(p); } private: WaitableUnitHeap* m_Heap; }; template inline void* WaitableUnitHeap::Allocator::Allocate(size_t size, s32 alignment) { if (size == m_Heap->GetUnitSize() && alignment >= 0 && m_Heap->GetUnitSize() % alignment == 0) { return m_Heap->Allocate(); } else { return 0; } } }} #endif #endif