1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     fnd_UnitHeap.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 16565 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_FND_FND_WAITABLEUNITHEAP_H_
17 #define NN_FND_FND_WAITABLEUNITHEAP_H_
18 
19 #include <nn/os.h>
20 #include <nn/fnd/fnd_UnitHeap.h>
21 
22 #ifdef __cplusplus
23 
24 namespace nn { namespace fnd {
25 
26 // not documented
27 // 未テスト
28 template <class LockPolicy = nn::os::LockPolicy::Object<nn::os::CriticalSection>, class Semaphore = nn::os::LightSemaphore>
29 class WaitableUnitHeap : private UnitHeapTemplate<LockPolicy>
30 {
31 private:
32 
33     typedef UnitHeapTemplate<LockPolicy> Base;
34     Semaphore m_Semaphore;
35 
36 public:
37 
38     using Base::GetRequiredHeapSize;
39 
WaitableUnitHeap()40     WaitableUnitHeap() {}
41 
42     WaitableUnitHeap(size_t unit, uptr addr, size_t size, s32 alignment = Base::DEFAULT_ALIGNMENT, bit32 option = 0)
43     {
44         Initialize(unit, addr, size, alignment, option);
45     }
46 
47     template <class MemoryBlock>
48     explicit WaitableUnitHeap(size_t unit, const MemoryBlock& block, s32 alignment = Base::DEFAULT_ALIGNMENT, bit32 option = 0)
49     {
50         Initialize(unit, block.GetAddress(), block.GetSize(), alignment, option);
51     }
52 
53     void Initialize(size_t unit, uptr addr, size_t size, s32 alignment = Base::DEFAULT_ALIGNMENT, bit32 option = 0)
54     {
55         Base::Initialize(unit, addr, size, alignment, option);
56         s32 maxCount = Base::GetTotalSize() / Base::GetUnitSize();
57         this->m_Semaphore.Initialize(maxCount, maxCount);
58     }
59 
60     using Base::Invalidate;
61 
62     /*!
63         @brief 終了処理
64     */
Finalize()65     void Finalize()
66     {
67         m_Semaphore.Finalize();
68         Base::Finalize();
69     }
70 
71     /*!
72         @brief ヒープからユニットに基づいてメモリを確保します。
73 
74         @return メモリへのポインタを返します。確保できるメモリがない場合は 0 を返します。
75     */
TryAllocate()76     void* TryAllocate()
77     {
78         if (m_Semaphore.TryAcquire())
79         {
80             void* ret = Base::Allocate();
81             NN_TASSERT_(ret);
82             return ret;
83         }
84         else
85         {
86             return 0;
87         }
88     }
89 
90     /*!
91         @brief ヒープからユニットに基づいてメモリを確保します。
92                確保できるメモリがない場合は、確保できるようになるまで待機します。
93 
94         @return メモリへのポインタを返します。
95     */
Allocate()96     void* Allocate()
97     {
98         m_Semaphore.Acquire();
99         void* ret = Base::Allocate();
100         NN_TASSERT_(ret);
101         return ret;
102     }
103 
104     /*!
105         @brief ヒープにメモリを解放します。
106 
107         @param[in] p 解放するメモリへのポインタ
108     */
Free(void * p)109     void Free(void* p)
110     {
111         Base::Free(p);
112         m_Semaphore.Release();
113     }
114 
115     /*!
116         @brief このヒープから確保したメモリを解放します。
117 
118                仮想メンバ関数であるため、HeapBaseから解放できます。
119 
120         @param[in] p メモリへのポインタを指定します。
121 	*/
FreeV(void * p)122     virtual void FreeV(void* p) { Free(p); }
123 
124     using Base::GetUnitSize;
125 
126     using Base::GetAllocatableCount;
127 
128     /*!
129         @brief ユニットヒープのメモリ領域の開始アドレスを取得します。
130 
131         @return ユニットヒープのメモリ領域の開始アドレスをを返します。
132      */
GetStartAddress()133     virtual void* GetStartAddress() const { return Base::GetStartAddress(); }
134 
135     /*!
136         @brief ユニットヒープに割り当てられているメモリサイズを取得します。
137 
138         @return ユニットヒープに割り当てられているメモリサイズを返します。
139      */
GetTotalSize()140     virtual size_t GetTotalSize() const { return Base::GetTotalSize(); }
141 
142     /*!
143         @brief ヒープ内部の情報を表示します。(デバッグ用)
144     */
Dump()145     virtual void Dump() const { Base::Dump(); }
146 
147     /*!
148         @brief  指定したアドレスがヒープに含まれているか調べます。
149 
150         @param[in]  addr    調べたいアドレスを指定します。
151 
152         @return ヒープに含まれていれば true を返し、含まれていなければ false を返します。
153 	*/
HasAddress(const void * addr)154     virtual bool HasAddress(const void* addr) const { return Base::HasAddress(addr); }
155 
156     class Allocator;
157 
158 };
159 
160 template <class LockPolicy, class Semaphore>
161 class WaitableUnitHeap<LockPolicy, Semaphore>::Allocator : public IAllocator
162 {
163 public:
164 
Allocator(WaitableUnitHeap & heap)165     Allocator(WaitableUnitHeap& heap) : m_Heap(&heap) {}
166 
Allocator()167     Allocator() : m_Heap(0) {}
168 
Initialize(WaitableUnitHeap & heap)169     void Initialize(WaitableUnitHeap& heap) { m_Heap = &heap; }
170 
GetHeap()171     WaitableUnitHeap* GetHeap() { return m_Heap; }
172 
GetHeap()173     const WaitableUnitHeap* GetHeap() const { return m_Heap; }
174 
175     virtual void* Allocate(size_t size, s32 alignment);
176 
Free(void * p)177     virtual void Free(void* p) { m_Heap->Free(p); }
178 
179 private:
180     WaitableUnitHeap* m_Heap;
181 };
182 
183 template <class LockPolicy, class Semaphore>
Allocate(size_t size,s32 alignment)184 inline void* WaitableUnitHeap<LockPolicy, Semaphore>::Allocator::Allocate(size_t size, s32 alignment)
185 {
186     if (size == m_Heap->GetUnitSize() && alignment >= 0 && m_Heap->GetUnitSize() % alignment == 0)
187     {
188         return m_Heap->Allocate();
189     }
190     else
191     {
192         return 0;
193     }
194 }
195 
196 }}
197 
198 #endif
199 
200 #endif
201