TNB Library
TnbStaticMemory.h
[詳解]
1#pragma once
11#include "TnbSingleton.h"
12
13
14
15//TNB Library
16namespace TNB
17{
18
19
20
65{
66public:
67
70 {
78 };
79
80private:
81
83 typedef DWORD TELL;
84
86 #define INVALID_TELL (ULONG_MAX)
87
89 class CManage
90 {
91 CSyncSection m_syncFunc;
95 class CInfo
96 {
97 DWORD m_dwLockCount;
98 DWORD m_dwSectorSize;
99 WORD m_wSectorCount;
100 WORD m_wCacheIndex;
101 WORD m_wCacheSecNo;
102 WORD m_wUsedSectors;
103 BYTE* m_pContent;
105 WORD *index(void) { return reinterpret_cast<WORD*>(m_pContent); }
107 WORD *flag(void)
108 {
109 return (m_pContent == NULL)
110 ? NULL
111 : reinterpret_cast<WORD*>(&m_pContent[sizeof(WORD) * m_wSectorCount]);
112 }
114 BYTE* data(WORD wSecNo)
115 {
116 return (m_pContent == NULL)
117 ? NULL
118 : &m_pContent[ sizeof(WORD) * m_wSectorCount +
119 sizeof(WORD) * m_wSectorCount +
120 m_dwSectorSize * wSecNo];
121 }
123 WORD m_IndexToSecNo(WORD i)
124 {
125 WORD* W = index();
126 ASSERTLIB(W[i] != 0);
127 return ToWord(W[i] & 0x7FFF);
128 }
137 DWORD m_AllocSub(WORD wStart, WORD wEnd, WORD wLen)
138 {
139 WORD wNext;
140 WORD* F = flag();
141 while ( wStart < wEnd )
142 {
143 wNext = static_cast<WORD>(F[wStart] & 0x7FFF);
144 if ( wNext == 0 )
145 {
146 wNext = m_wSectorCount;
147 }
148 if ( (F[wStart] & 0x8000) == 0 && (wNext - wStart) >= wLen )
149 {
150 //期待セクタ数の空きがあった
151 WORD w = static_cast<WORD>(wStart + wLen);
152 if ( w >= m_wSectorCount )
153 {
154 w = 0;
155 }
156 for ( WORD i = 0; i < wLen; i++ )
157 {
158 F[wStart + i] = static_cast<WORD>(0x8000 | w);
159 }
160 m_wCacheSecNo = w;
161 return wStart;
162 }
163 wStart = wNext;
164 }
165 return INVALID_TELL;
166 }
167 public:
168 CSyncSection syncBank;
170 CInfo(void)
171 {
172 m_wCacheIndex = 0;
173 m_wCacheSecNo = 0;
174 m_wUsedSectors = 0;
175 m_dwLockCount = 0;
176 m_dwSectorSize = 0;
177 m_wSectorCount = 0;
178 m_pContent = NULL;
179 }
181 ~CInfo(void)
182 {
183 if ( m_pContent != NULL )
184 {
185 delete[] m_pContent;
186 m_pContent = NULL;
187 }
188 }
190 WORD GetSectorCount(void) { return m_wSectorCount; }
192 bool IsValid(void) { return m_pContent != NULL; }
199 EResult Create(DWORD dwSectorSize, WORD wSectorCount)
200 {
201 EXCLUSIVE(&syncBank);
202 if ( m_pContent != NULL ) { return ER_ExistBank; }
203 if ( dwSectorSize < 16 ) { return ER_InvalidParam; }
204 if ( wSectorCount < 10 || wSectorCount >= 32768) { return ER_InvalidParam; }
205 m_pContent = new BYTE[sizeof(WORD) * wSectorCount + (sizeof(WORD) + dwSectorSize) * wSectorCount];
206 if ( m_pContent == NULL ){ return ER_OutOfMemory; }
207 memset(m_pContent, 0, sizeof(WORD) * wSectorCount + sizeof(WORD) * wSectorCount);
208 m_dwSectorSize = dwSectorSize;
209 m_wSectorCount= wSectorCount;
210 return ER_Success;
211 }
213 void Delete(void)
214 {
215 EXCLUSIVE(&syncBank);
216 #ifdef _DEBUG
217 if ( m_dwLockCount != 0 )
218 {
219 TRACE0("CStaticMemory::CManage::Delete() ; Lock/Unlockの回数が合っていません。\n");
220 }
221 #endif
222 if ( m_pContent != NULL )
223 {
224 delete[] m_pContent;
225 m_pContent = NULL;
226 }
227 m_wCacheSecNo = 0;
228 m_wCacheIndex = 0;
229 m_wUsedSectors = 0;
230 m_dwLockCount = 0;
231 }
238 EResult Resize(WORD wSectorCount)
239 {
240 EXCLUSIVE(&syncBank);
241 if ( wSectorCount == 0 )
242 {
243 wSectorCount = m_wSectorCount;
244 }
245 else if ( m_wUsedSectors > wSectorCount )
246 {
247 return ER_OutOfMemory; //足りなくなる
248 }
249 else if ( m_wSectorCount > wSectorCount )
250 {
251 return ER_InvalidParam; //小さくなる
252 }
253 if ( m_pContent == NULL ){ return ER_NotFoundBank; }
254 CInfo infoNew;
255 EResult rc = infoNew.Create(m_dwSectorSize, wSectorCount);
256 if ( rc != ER_Success ){ return rc; }
257 //
258 WORD* W = index();
259 WORD* newW = infoNew.index();
260 WORD* F = flag();
261 WORD wPos;
262 for ( WORD i = 0; i < m_wSectorCount; i++ )
263 {
264 wPos = W[i];
265 if ( wPos != 0 )
266 {
267 wPos &= 0x7FFF;
268 WORD wLen = static_cast<WORD>((F[wPos] & 0x7FFF) - wPos);
269 DWORD r = infoNew.m_AllocSub(infoNew.m_wCacheSecNo, wSectorCount, wLen);
270 if ( r == INVALID_TELL && infoNew.m_wCacheSecNo != 0 )
271 {
272 r = infoNew.m_AllocSub(0, infoNew.m_wCacheSecNo, wLen);
273 }
274 ASSERTLIB(r != INVALID_TELL);
275 BYTE* P = infoNew.data(ToWord(r));
276 ASSERTLIB(P != NULL);
277 MemCopy(P, data(wPos), wLen * m_dwSectorSize);
278 newW[i] = ToWord(0x8000 | r);
279 }
280 }
281 m_wSectorCount= wSectorCount;
282 m_wCacheSecNo = 0;
283 m_wCacheIndex = 0;
284 delete[] m_pContent;
285 m_pContent = infoNew.m_pContent;
286 infoNew.m_pContent = NULL;
287 return ER_Success;
288 }
292 WORD GetUsedSectors(void)
293 {
294 return m_wUsedSectors;
295 }
302 DWORD Allocate(size_t size)
303 {
304 EXCLUSIVE(&syncBank);
305 if ( m_pContent == NULL ){ return INVALID_TELL; }
306 WORD wLen = ToWord((ToDword(size) + m_dwSectorSize - 1) / m_dwSectorSize);
307 if ( wLen + m_wUsedSectors > m_wSectorCount ){ return INVALID_TELL; }
308 DWORD r = m_AllocSub(m_wCacheSecNo, m_wSectorCount, wLen);
309 if ( r == INVALID_TELL && m_wCacheSecNo != 0 )
310 {
311 r = m_AllocSub(0, m_wCacheSecNo, wLen);
312 }
313 if ( r == INVALID_TELL )
314 {
315 return r;
316 }
317 //
318 m_wUsedSectors = static_cast<WORD>(m_wUsedSectors + wLen);
319 WORD* W = index();
320 for ( WORD i = m_wCacheIndex; i < m_wSectorCount; i++ )
321 {
322 if ( W[i] == 0 )
323 {
324 W[i] = ToWord(0x8000 | r);
325 m_wCacheIndex = i;
326 return i;
327 }
328 }
329 for ( WORD i = 0; i < m_wCacheIndex; i++ )
330 {
331 if ( W[i] == 0 )
332 {
333 W[i] = ToWord(0x8000 | r);
334 m_wCacheIndex = i;
335 return i;
336 }
337 }
338 ASSERTLIB(false);
339 return INVALID_TELL;
340 }
347 bool Free(WORD wIndex)
348 {
349 EXCLUSIVE(&syncBank);
350 if ( m_pContent == NULL ){ return false; } // プールなし
351 if ( wIndex >= m_wSectorCount ){ return false; } // 番号異常
352 WORD wSecNo = m_IndexToSecNo(wIndex);
353 ASSERTLIB(wSecNo < m_wSectorCount);
354 WORD* F = flag();
355 if ( (F[wSecNo] & 0x8000) == 0 ){ return false; } // 確保していない
356 m_wCacheSecNo = wSecNo;
357 WORD w;
358 WORD wNext = static_cast<WORD>(F[wSecNo] & 0x7FFF);
359 if ( wNext == 0 )
360 {
361 //= 最後。全部0にしちゃう
362 wNext = m_wSectorCount;
363 w = 0;
364 }
365 else
366 {
367 //= 次のブロック確認
368 if ( (F[wNext] & 0x8000) != 0 )
369 {
370 //確保している.次のブロックはNext
371 w = wNext;
372 }
373 else
374 {
375 //確保していない。次のブロックの次にする。
376 w = F[wNext];
377 }
378 }
379 for ( WORD i = wSecNo; i < wNext; i++ )
380 {
381 F[i] = w;
382 }
383 index()[wIndex] = 0;
384 m_wCacheIndex = wIndex;
385 m_wUsedSectors = static_cast<WORD>(m_wUsedSectors - (wNext - wSecNo));
386 return true;
387 }
396 size_t GetSize(WORD wIndex)
397 {
398 EXCLUSIVE(&syncBank);
399 if ( wIndex >= m_wSectorCount ){ return INVALID_TELL; } // 番号異常
400 WORD wSecNo = m_IndexToSecNo(wIndex);
401 ASSERTLIB(wSecNo < m_wSectorCount);
402 WORD* F = flag();
403 if ( (F[wSecNo] & 0x8000) == 0 ){ return INVALID_TELL; } //確保してない
404 if ( wSecNo != 0 )
405 {
406 if ( F[wSecNo - 1] == F[wSecNo] ){ return INVALID_TELL; }//一つ前と同じのはずがない
407 }
408 return ((F[wSecNo] & 0x7FFF) - wSecNo) * m_dwSectorSize;
409 }
414 DWORD GetLockCount(void) { return m_dwLockCount; }
422 LPVOID Lock(WORD wIndex)
423 {
424 EXCLUSIVE(&syncBank);
425 if ( GetSize(wIndex) == INVALID_TELL ){ return NULL; }
426 WORD wSecNo = m_IndexToSecNo(wIndex);
427 ASSERTLIB(wSecNo < m_wSectorCount);
428 ASSERT0(data(wSecNo) != NULL, "CStaticMemory::CManage::CInfo::Lock()", "確保していません");
429 m_dwLockCount++;
430 return data(wSecNo);
431 }
432
437 void Unlock(void)
438 {
439 m_dwLockCount--;
440 }
441 private:
442 friend class CStaticMemoryTest;
443 }; // CINfo
444
445 //--------------------
446
447 CInfo* m_pInfo;
449 SINGLETON_CONSTRUCTOR(CManage)
450 {
451 m_pInfo = new CInfo[256];
452 ASSERT( m_pInfo != NULL );
453 }
459 bool m_CheckTell(TELL& tell, BYTE& bank)
460 {
461 bank = static_cast<BYTE>(tell >> 24);
462 tell &= 0x0000FFFF;
463 if ( ! m_pInfo[bank].IsValid() ){ return false; }
464 return m_pInfo[bank].GetSectorCount() > tell;
465 }
466 public:
468 ~CManage(void)
469 {
470 if ( m_pInfo != NULL )
471 {
472 delete[] m_pInfo;
473 m_pInfo = NULL;
474 }
475 }
484 EResult CreateBank(BYTE bank, DWORD dwSectorSize, WORD wSectorCount)
485 {
486 EXCLUSIVE(&m_syncFunc);
487 return m_pInfo[bank].Create(dwSectorSize, wSectorCount);
488 }
497 EResult DeleteBank(BYTE bank, bool boIsForce = false)
498 {
499 EXCLUSIVE2(&m_syncFunc,&m_pInfo[bank].syncBank);
500 if ( ! m_pInfo[bank].IsValid() ){ return ER_NotFoundBank; }
501 if ( ! boIsForce && m_pInfo[bank].GetLockCount() != 0 ){ return ER_Locked; }
502 m_pInfo[bank].Delete();
503 return ER_Success;
504 }
514 EResult ResizeBank(BYTE bank, WORD wSectorCount = 0)
515 {
516 EXCLUSIVE2(&m_syncFunc,&m_pInfo[bank].syncBank);
517 if ( ! m_pInfo[bank].IsValid() ){ return ER_NotFoundBank; }
518 if ( m_pInfo[bank].GetLockCount() != 0 ){ return ER_Locked; }
519 return m_pInfo[bank].Resize(wSectorCount);
520 }
528 WORD GetUsedSectors(BYTE bank)
529 {
530 return static_cast<WORD>(m_pInfo[bank].IsValid() ? m_pInfo[bank].GetUsedSectors() : 0);
531 }
540 TELL Allocate(BYTE bank, size_t size)
541 {
542 if ( size == 0 || ! m_pInfo[bank].IsValid() ){ return INVALID_TELL; }
543 DWORD dw = m_pInfo[bank].Allocate(size);
544 return (dw == INVALID_TELL) ? INVALID_TELL : ((bank << 24) | dw);
545 }
552 bool Free(TELL tell)
553 {
554 BYTE bank;
555 return m_CheckTell(tell, bank) ? m_pInfo[bank].Free(ToWord(tell)) : false;
556 }
564 size_t GetSize(TELL tell)
565 {
566 BYTE bank;
567 return m_CheckTell(tell, bank) ? m_pInfo[bank].GetSize(ToWord(tell)) : 0;
568 }
577 LPVOID Lock(TELL tell)
578 {
579 BYTE bank;
580 return m_CheckTell(tell, bank) ? m_pInfo[bank].Lock(ToWord(tell)) : NULL;
581 }
582
589 bool Unlock(TELL tell)
590 {
591 BYTE bank;
592 if ( ! m_CheckTell(tell, bank) ){ return false; }
593 m_pInfo[bank].Unlock();
594 return true;
595 }
596
597 private:
598 friend class CStaticMemoryTest;
599 }; // CManage
600
601 //--------------------
602
603 CManage* m_pMan;
604 TELL m_tell;
605 DWORD m_dwParam;
607 void m_Init(void)
608 {
609 m_dwParam = 0;
610 m_pMan = CManage::GetInstance();
611 m_tell = INVALID_TELL;
612 }
613
614public:
615
628 static EResult CreateBank(BYTE bank, DWORD dwSectorSize, WORD wSectorCount)
629 {
630 return CManage::GetInstance()->CreateBank(bank, dwSectorSize, wSectorCount);
631 }
632
643 static EResult DeleteBank(BYTE bank, bool boIsForce = false)
644 {
645 return CManage::GetInstance()->DeleteBank(bank, boIsForce);
646 }
647
662 static EResult ResizeBank(BYTE bank, WORD wSectorCount = 0)
663 {
664 return CManage::GetInstance()->ResizeBank(bank, wSectorCount);
665 }
666
669 {
670 Free();
671 }
672
675 {
676 m_Init();
677 }
678
684 {
685 m_Init();
686 operator=(h);
687 }
688
695 {
696 Free();
697 if ( other.m_tell != INVALID_TELL )
698 {
699 LONG* B = static_cast<LONG*>(m_pMan->Lock(other.m_tell));
700 ::InterlockedIncrement(B);
701 m_pMan->Unlock(other.m_tell);
702 m_tell = other.m_tell;
703 }
704 m_dwParam = other.m_dwParam;
705 return *this;
706 }
707
712 DWORD GetParam(void)
713 {
714 return m_dwParam;
715 }
716
721 void SetParam(DWORD dwParam)
722 {
723 m_dwParam = dwParam;
724 }
725
734 {
735 if ( m_tell == INVALID_TELL){ return 0; }
736 LONG* B = static_cast<LONG*>(m_pMan->Lock(m_tell));
737 LONG r = *B;
738 m_pMan->Unlock(m_tell);
739 return r;
740 }
741
747 bool HasMemory(void)
748 {
749 return m_tell!=INVALID_TELL;
750 }
751
761 bool Allocate(BYTE bank, size_t size)
762 {
763 Free();
764 TELL t = m_pMan->Allocate(bank, size + sizeof(LONG));//カウンタ分多く
765 if ( t == INVALID_TELL )
766 {
767 return false;
768 }
769 LONG* P = static_cast<LONG*>(m_pMan->Lock(t));
770 if ( P == NULL )
771 {
772 m_pMan->Free(t);
773 return false;
774 }
775 *P = 1; //カウンタ初期化
776 m_pMan->Unlock(t);
777 m_tell = t;
778 return true;
779 }
780
786 void Free(void)
787 {
788 if ( m_tell == INVALID_TELL) { return; }
789 LONG* B = static_cast<LONG*>(m_pMan->Lock(m_tell));
790 if ( ::InterlockedDecrement(B) == 0 )
791 {
792 m_pMan->Unlock(m_tell);
793 m_pMan->Free(m_tell);
794 }
795 else
796 {
797 m_pMan->Unlock(m_tell);
798 }
799 m_tell=INVALID_TELL;
800 }
801
808 size_t GetSize(void)
809 {
810 if ( m_tell == INVALID_TELL ){ return 0; }
811 size_t l = m_pMan->GetSize(m_tell);
812 if ( l != 0 )
813 {
814 l -= sizeof(LONG);
815 }
816 return l;
817 }
818
825 LPVOID Lock(void)
826 {
827 if ( m_tell == INVALID_TELL ) { return NULL; }
828 LONG* B = static_cast<LONG*>(m_pMan->Lock(m_tell));
829 return &B[1];
830 }
831
836 void Unlock(void)
837 {
838 if ( m_tell != INVALID_TELL )
839 {
840 m_pMan->Unlock(m_tell);
841 }
842 }
843
844private:
845 friend class CStaticMemoryTest;
846};
847
848
849
850};//TNB
851
852
853
854#ifndef _TnbDOXYGEN //Document作成用シンボル
855#if 0
856 //m_pContent の確保内容
857 [Indexテーブル][Flagテーブル][内容]という並び。
858 //Indexテーブル
859 並びはIndex順。
860 TELLの下位WORD(Index)とセクタNoを関連付けるテーブル。最上位BIT
861 が立っていたら使用(下位15BITがSecNo)
862 Resize、デフラグしても並びは変換しない。
863 // Flagテーブル&内容
864 いずれも並びはSecNo順。
865 Flag用DWORDをセクタ数確保。
866 セクタサイズのメモリをセクタ数確保。
867 Flag用は、次の空きセクタ番号を保持。0なら最後を指す。
868 つまり起動時はすべて0。
869 確保すると、複数の確保したセクタすべて最上位ビットが立ち、
870 次のブロックの先頭セクタ番号が入る。
871 ex)
872 <0> <1> <2> <3> <4> <5> <6>
873 起動時
874 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
875 2ブロック確保
876 0x8002,0x8002,0x0000,0x0000,0x0000,0x0000,0x0000,
877 さらに3ブロック確保
878 0x8002,0x8002,0x8005,0x8005,0x8005,0x0000,0x0000,
879 最初の2ブロック開放
880 0x0002,0x0002,0x8005,0x8005,0x8005,0x0000,0x0000,
881 1ブロック確保
882 0x8001,0x0002,0x8005,0x8005,0x8005,0x0000,0x0000,
883
884 つまりチェーンと使用フラグとブロック長がわかるようになる。
885#endif
886#endif
シングルトン関係のヘッダ
#define INVALID_TELL
静的メモリ管理クラス用エラー値宣言
静的メモリ管理クラス
CStaticMemory & operator=(const CStaticMemory &other)
[代入] コピーオペレータ
size_t GetSize(void)
[取得] 確保サイズ取得
void Unlock(void)
[取得] アンロック
bool Allocate(BYTE bank, size_t size)
[取得] メモリ確保
CStaticMemory(void)
コンストラクタ
static EResult ResizeBank(BYTE bank, WORD wSectorCount=0)
[設定] バンクのりサイズ.
DWORD GetParam(void)
[取得] パラメータ取得
~CStaticMemory(void)
デストラクタ
CStaticMemory(const CStaticMemory &h)
コピーコンストラクタ
@ ER_Locked
ロックされています。
@ ER_InvalidTell
不正なTELLです。
@ ER_ExistBank
すでにバンクがあります。
@ ER_InvalidParam
不正なパラメータです。
@ ER_NotFoundBank
バンクが見つかりません。
@ ER_OutOfMemory
メモリが足りません。
static EResult DeleteBank(BYTE bank, bool boIsForce=false)
[設定] バンク削除.
bool HasMemory(void)
[確認] メモリ保持確認
LONG GetJointlyCount(void)
[取得] 共有数取得.
LPVOID Lock(void)
[取得] アドレス取得&ロック.
void SetParam(DWORD dwParam)
[代入] パラメータ設定
static EResult CreateBank(BYTE bank, DWORD dwSectorSize, WORD wSectorCount)
[設定] バンク作成.
void Free(void)
[取得] メモリ解放
Section排他管理クラス
Definition: TnbSync.h:125
#define SINGLETON_CONSTRUCTOR(CLS)
シングルトン作成マクロ
Definition: TnbSingleton.h:60
DWORD ToDword(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:395
#define EXCLUSIVE2(CLS1, CLS2)
簡易排他ツイン制御マクロ.
Definition: TnbSync.h:820
#define EXCLUSIVE(CLS)
簡易排他制御マクロ.
Definition: TnbSync.h:788
TNB Library
Definition: TnbDoxyTitle.txt:2
void MemCopy(T *_pDst, const void *pSrc, size_t len)
[複製] メモリコピー
Definition: TnbDef.h:376