WarSMemory.cpp
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:19k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. // See the "War Software Series License Agreement" for details concerning 
  2. // use and distribution.
  3. // ---
  4. // This source code, executables and programs containing source code or
  5. // binaries or proprietetary technology from the War Software Series are
  6. // NOT alloed used, viewed or tested by any governmental agencies in
  7. // any countries. This includes the government, departments, police, 
  8. // military etc.
  9. // ---
  10. // This file is intended for use with Tab space = 2
  11. // Created and maintained in MSVC Developer Studio
  12. // ---
  13. // NAME : WarSMemory.cpp
  14. // PURPOSE : Shared memory management and thread/process synchronization
  15. // PROGRAM : 
  16. // DATE : March 9 1997
  17. // AUTHOR : Jarle Aase
  18. // ---
  19. // 
  20. // REVISION HISTORY
  21. // 
  22. // Extended logging and testing from shared memory submodule
  23. #define SMEM_DEBUG 0
  24. #include "stdafx.h"
  25. #include "WarSoftware.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. ////////////////////////////////////////////////////////////////////////////////////
  32. // CGlobalLock
  33. CGlobalLock::CGlobalLock(LPCSTR Name)
  34. {
  35. m_pSemaphore = new  CSemaphore(1, 1, Name);
  36. m_pSligleLock = new CSingleLock(m_pSemaphore);
  37. m_pSligleLock->Lock();
  38. }
  39. CGlobalLock::~CGlobalLock()
  40. {
  41. m_pSligleLock->Unlock();
  42. delete m_pSligleLock;
  43. delete m_pSemaphore;
  44. }
  45. ////////////////////////////////////////////////////////////////////////////////////
  46. // CSharedMemSegment
  47. #ifdef _DEBUG
  48. const unsigned short CSharedBlksMem::tag_FreeWatermark[4] = {0xfeee, 0xfeee, 0xfeee, 0xfeee};
  49. const unsigned short CSharedBlksMem::tag_UsedWatermark[4] = {0,0,0,0};
  50. #endif
  51. CSharedMemSegment::CSharedMemSegment()
  52. {
  53. m_Name = "** Not initialized ***";
  54. m_hMMFile = NULL;
  55. m_Size = 0;
  56. m_pSMH = NULL;
  57. #if SMEM_DEBUG
  58. CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedMemSegment(%08x) - New segment allocated.", (DWORD)this);
  59. #endif
  60. }
  61. CSharedMemSegment::~CSharedMemSegment()
  62. {
  63. if (m_hMMFile)
  64. CloseHandle(m_hMMFile);
  65. m_hMMFile = NULL;
  66. #if SMEM_DEBUG
  67. CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM ~CSharedMemSegment(%08x) - segment deleted.", (DWORD)this);
  68. #endif
  69. }
  70. LPVOID CSharedMemSegment::Create(LPCSTR Name, DWORD Size, BOOL KeepInMemory)
  71. {
  72. CGlobalLock Lock(LNAME_SHARED_MEM_SEGMENT);
  73. #if SMEM_DEBUG
  74. CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedMemSegment::Create(%08x) - creating %s (%d bytes)", 
  75. (DWORD)this, Name, Size);
  76. #endif
  77. BOOL WeMustInitialize = FALSE;
  78. if (!(m_hMMFile = OpenFileMapping (FILE_MAP_WRITE, 
  79. FALSE, 
  80. Name)))
  81. {
  82. if (!(m_hMMFile = CreateFileMapping ((HANDLE)0xFFFFFFFF,
  83. NULL,
  84. PAGE_READWRITE | SEC_COMMIT | (KeepInMemory ? SEC_NOCACHE : 0) ,
  85. 0,
  86. (m_Size = Size) + sizeof(SHARED_MEM_SEG_HDR),
  87. Name)))
  88. return NULL;
  89. WeMustInitialize = TRUE;
  90. }
  91. LPVOID __hdr__Ptr = MapViewOfFile(m_hMMFile, FILE_MAP_WRITE, 0,0,0);
  92. if (!__hdr__Ptr)
  93. {
  94. CloseHandle(m_hMMFile);
  95. m_hMMFile = NULL;
  96. return NULL;
  97. }
  98. m_pSMH = (SHARED_MEM_SEG_HDR *)__hdr__Ptr;
  99. if (WeMustInitialize)
  100. {
  101. memset(__hdr__Ptr, 0, Size + sizeof(SHARED_MEM_SEG_HDR));
  102. m_pSMH->Size = Size + sizeof(SHARED_MEM_SEG_HDR);
  103. m_pSMH->AccessCnt = 0;
  104. strcpy(m_pSMH->Name, Name);
  105. for(int i = 0; i < SHMEM_NUM_USER_PTRS; i++)
  106. m_pSMH->pUserPtr[i] = NULL;
  107. }
  108. if (m_pSMH->Size != (Size + sizeof(SHARED_MEM_SEG_HDR)))
  109. {
  110. CloseHandle(m_hMMFile);
  111. m_hMMFile = NULL;
  112. return NULL;
  113. }
  114. m_pSMH->AccessCnt++;
  115. return (char *)GetDataPtr();
  116. }
  117. ///////////////////////////////////////////////////////////////////////////////////////
  118. // CSharedBlksMem
  119. CSharedBlksMem::CSharedBlksMem()
  120. {
  121. m_Mutex = NULL;
  122. memset(m_Blks, 0, sizeof(m_Blks));
  123. m_Name = "";
  124. m_SegmentSize = 0;
  125. m_IsInitialized = FALSE;
  126. #if SMEM_DEBUG
  127. CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedBlksMem(%08x) - created", 
  128. (DWORD)this);
  129. #endif
  130. }
  131. CSharedBlksMem::~CSharedBlksMem()
  132. {
  133. if (m_Mutex != NULL)
  134. CloseHandle(m_Mutex);
  135. #if SMEM_DEBUG
  136. CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM ~CSharedBlksMem(%08x) - destroyed", 
  137. (DWORD)this);
  138. #endif
  139. }
  140. BOOL CSharedBlksMem::Create(LPCSTR Name, DWORD BlkSize)
  141. {
  142. ASSERT(m_IsInitialized == FALSE); // Only initialize once
  143. m_Name = Name;
  144. m_SegmentSize = BlkSize;
  145. #if SMEM_DEBUG
  146. CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedBlksMem::Create(%08x) - creating %s (%d bytes)", 
  147. (DWORD)this, Name, BlkSize);
  148. #endif
  149. if (!Initialize())
  150. return FALSE;
  151. if (!AllocSegment(0))
  152. return FALSE;
  153. return TRUE;
  154. }
  155. // Initialize mutex and (eventually) super block
  156. BOOL CSharedBlksMem::Initialize()
  157. {
  158. ASSERT(m_IsInitialized == FALSE); // Only initialize once
  159. CGlobalLock Lock(LNAME_SHARED_MEM_SEGMENT);
  160. m_IsInitialized = TRUE;
  161. if ((m_Mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, SHMEM_BLKS_MUTEX_NAME)) == NULL)
  162. m_Mutex = CreateMutex(NULL, FALSE, SHMEM_BLKS_MUTEX_NAME);
  163. return m_Mutex != NULL;
  164. }
  165. // 
  166. BOOL CSharedBlksMem::AllocSegment(int Index)
  167. {
  168. BOOL Rval;
  169. #if SMEM_DEBUG
  170. CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedBlksMem::AllocSegment() - Allocating (Index = %d)", 
  171. Index);
  172. #endif
  173. if (Index >= SHARED_MEM_MAX_BLKS)
  174. {
  175. CLog::GetLog()->LogMsg(LOGF_WARNINGS,
  176. "CSharedBlksMem::AllocSegment() - Out of memory. %d segments, each %d bytes are in use",
  177. SHARED_MEM_MAX_BLKS, m_SegmentSize);
  178. CLog::GetLog()->LogMsg(LOGF_WARNINGS,
  179. "CSharedBlksMem::AllocSegment() - You should increase the segment size.",
  180. SHARED_MEM_MAX_BLKS, m_SegmentSize);
  181. return FALSE; // Out of memory
  182. }
  183. WaitForSingleObject(m_Mutex, INFINITE);
  184. ASSERT(m_Blks[Index] == NULL);
  185. CString SegName;
  186. SegName.Format("%s%d", m_Name, Index);
  187. Rval = (m_Blks[Index] = m_Segments[Index].Create(SegName, m_SegmentSize)) != NULL;
  188. if (Rval)
  189. {
  190. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  191. SUPER_MEM_BLKS_HDR *pBlkHdr = (SUPER_MEM_BLKS_HDR *)m_Blks[Index];
  192. SHARED_MEM_SEG_HDR *pSegHdr = m_Segments[Index].m_pSMH;
  193. if (!pBlkHdr->IsInitialized)
  194. {
  195. pSuper->NumUsedSegments++;
  196. pBlkHdr->PhysMemory = sizeof(SUPER_MEM_BLKS_HDR);
  197. pBlkHdr->IsInitialized = TRUE;
  198. pBlkHdr->SegmentSize = pSegHdr->Size - sizeof(SHARED_MEM_SEG_HDR);
  199. // Add one free node at the size of the entire segment
  200. VIRTUAL_FREE_MEM_NODE_HDR *pNode 
  201. = (VIRTUAL_FREE_MEM_NODE_HDR *)(((char *)m_Blks[Index]) + sizeof(SUPER_MEM_BLKS_HDR));
  202. pNode->node_hdr.isfree = TRUE;
  203. pNode->node_hdr.hasnext = FALSE;
  204. pNode->node_hdr.size = pBlkHdr->SegmentSize - sizeof(SUPER_MEM_BLKS_HDR);
  205. pNode->node_hdr.prev = 0;
  206. pNode->nextfree = 0;
  207. // Link it to the list
  208. __LinkFree(Index, pNode);
  209. }
  210. }
  211. ReleaseMutex(m_Mutex);
  212. return Rval;
  213. }
  214. // Link a free node to the first entry in the appropriate free list.
  215. void CSharedBlksMem::__LinkFree(int Segment, VIRTUAL_FREE_MEM_NODE_HDR *pNode)
  216. {
  217. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  218. VIRTUAL_FREE_MEM_NODE_HDR *pLink;
  219. int LenIndex = GetLenIndex(&pNode->node_hdr);
  220. SMEM me = Smem(pNode, Segment);
  221. // Always link as first
  222. pLink = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pSuper->FreeTable[LenIndex]);
  223. pNode->prevfree = 0;
  224. pNode->index = LenIndex;
  225. #ifdef _DEBUG
  226. // Link free
  227. memcpy(pNode->node_hdr.watermark, tag_FreeWatermark, sizeof(tag_FreeWatermark));
  228. #endif
  229. if (pLink)
  230. {
  231. pNode->nextfree = pSuper->FreeTable[LenIndex];
  232. pLink->prevfree = me;
  233. }
  234. else
  235. {
  236. pNode->nextfree = 0;
  237. }
  238. pNode->node_hdr.isfree = TRUE;
  239. pSuper->FreeTable[LenIndex] = me;
  240. }
  241. // Unlink a node from the free chain
  242. void CSharedBlksMem::__UnlinkFree(int ListIndex, SMEM me)
  243. {
  244. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  245. VIRTUAL_FREE_MEM_NODE_HDR *pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(me);
  246. VIRTUAL_FREE_MEM_NODE_HDR *pRootNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pSuper->FreeTable[ListIndex]);
  247. VIRTUAL_FREE_MEM_NODE_HDR *pPrevNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->prevfree);
  248. VIRTUAL_FREE_MEM_NODE_HDR *pNextNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->nextfree);
  249. if (!pPrevNode)
  250. {
  251. // Root
  252. pSuper->FreeTable[ListIndex] = pNode->nextfree;
  253. }
  254. else
  255. {
  256. pPrevNode->nextfree = pNode->nextfree;
  257. }
  258. if (pNextNode)
  259. pNextNode->prevfree = pNode->prevfree;
  260. #ifdef _DEBUG
  261. // Tag as used
  262. ASSERT(memcmp(pNode->node_hdr.watermark, tag_FreeWatermark, sizeof(tag_FreeWatermark)) == 0);
  263. memcpy(pNode->node_hdr.watermark, tag_UsedWatermark, sizeof(tag_UsedWatermark));
  264. ASSERT(pNode->node_hdr.isfree == TRUE);
  265. #endif
  266. pNode->node_hdr.isfree = FALSE;
  267. }
  268. // Return the free list index of the node, based on it's size
  269. // There are SMEM_NUM_BLK_SIZES lists of free nodes, each with
  270. // free sizes <= the desired size (physical size - header)
  271. int CSharedBlksMem::GetLenIndex(VIRTUAL_MEM_NODE_HDR *pNode)
  272. {
  273. return GetLenIndex(GetNodeDataLen(pNode));
  274. }
  275. int CSharedBlksMem::GetLenIndex(int MinSize)
  276. {
  277. static int SizeTable[SMEM_NUM_BLK_SIZES];
  278. if (SizeTable[0] == 0)
  279. {
  280. // Initialize
  281. int val = SMEM_NUM_BLK_SIZES_BASE;
  282. for(int Index = 0; Index < (SMEM_NUM_BLK_SIZES -1); Index ++)
  283. {
  284. SizeTable[Index] = val;
  285. val *= 2;
  286. }
  287. SizeTable[SMEM_NUM_BLK_SIZES -1] = 0xffffff; // Max 24 bit value
  288. }
  289. for(int Index = 0; Index < (SMEM_NUM_BLK_SIZES -1); Index ++)
  290. {
  291. if (SizeTable[Index] >= MinSize)
  292. break;
  293. }
  294. return Index;
  295. }
  296. BOOL CSharedBlksMem::sh_malloc(SMEM& me, DWORD nBytes)
  297. {
  298. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  299. me = 0;
  300. BOOL Rval = FALSE;
  301. if (nBytes >= (pSuper->SegmentSize - sizeof(SUPER_MEM_BLKS_HDR)))
  302. {
  303. CLog::GetLog()->LogMsg(LOGF_WARNINGS,
  304. "CSharedBlksMem::sh_malloc() - %d bytes requested, segment size is %d bytes(avail). Increase segment size.",
  305. nBytes, pSuper->SegmentSize - sizeof(SUPER_MEM_BLKS_HDR));
  306. return FALSE;
  307. }
  308. int ListIndex = GetLenIndex(nBytes);
  309. WaitForSingleObject(m_Mutex, INFINITE);
  310. AssertValidFreeTables();
  311. Rescan();
  312. if ((Rval = __FindFreeNode(me, nBytes, ListIndex)) == FALSE)
  313. Rval = __AllocNewNode(me, nBytes, ListIndex);
  314. AssertValidFreeTables();
  315. ReleaseMutex(m_Mutex);
  316. return Rval;
  317. }
  318. BOOL CSharedBlksMem::sh_realloc(SMEM& shm, DWORD nBytes)
  319. {
  320. SMEM new_mem;
  321. if (sh_malloc(new_mem, nBytes))
  322. {
  323. VIRTUAL_MEM_NODE_HDR *pNode = __hdr__Ptr(shm);
  324. VIRTUAL_MEM_NODE_HDR *pNewNode = __hdr__Ptr(new_mem);
  325. memcpy(pNewNode, pNode, min(nBytes, pNode->size));
  326. sh_free(shm);
  327. shm = new_mem;
  328. return TRUE;
  329. }
  330. return FALSE;
  331. }
  332. void CSharedBlksMem::sh_free(SMEM shm)
  333. {
  334. WaitForSingleObject(m_Mutex, INFINITE);
  335. AssertValidFreeTables();
  336. VIRTUAL_FREE_MEM_NODE_HDR *pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(shm);
  337. VIRTUAL_FREE_MEM_NODE_HDR *pPrev = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->node_hdr.prev);
  338. VIRTUAL_FREE_MEM_NODE_HDR *pNext = (VIRTUAL_FREE_MEM_NODE_HDR *)((char *)pNode) + pNode->node_hdr.size;
  339. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  340. pSuper->UserMemory -= (pNode->node_hdr.size - sizeof(VIRTUAL_MEM_NODE_HDR));
  341. pSuper->PhysMemory -= pNode->node_hdr.size;
  342. BOOL HasNext = pNode->node_hdr.hasnext;
  343. // See if prev node is free, and withing the same segment. If it is, merge the two nodes.
  344. if (pPrev && pPrev->node_hdr.isfree && (pNode->node_hdr.prev.blk == shm.blk))
  345. {
  346. pPrev->node_hdr.size += pNode->node_hdr.size;
  347. pSuper->NumNodes--;
  348. pNode = pPrev;
  349. __UnlinkFree(pNode->index, Smem(pPrev, shm.blk));
  350. }
  351. // See if next node is free. If it is, merge the two nodes.
  352. if (HasNext)
  353. {
  354. if (pNext->node_hdr.isfree)
  355. {
  356. ASSERT(pNext->node_hdr.prev == shm);
  357. pNode->node_hdr.size += pNext->node_hdr.size;
  358. pSuper->NumNodes--;
  359. __UnlinkFree(pNext->index, Smem(pNext, shm.blk));
  360. }
  361. }
  362. pSuper->NumNodes--;
  363. // Link it
  364. __LinkFree(shm.blk, pNode);
  365. AssertValidFreeTables();
  366. ReleaseMutex(m_Mutex);
  367. }
  368. // Try to find (and take) a free node
  369. // This function will perform a sequentional scan for a 
  370. // node that fit on the free node linked list where a node of
  371. // the required size _might_ exist. If we looked at the next
  372. // free list index, all nodes will fit, but this will result
  373. // in more memory fragmentation.
  374. // The current implementation use a little more CPU to
  375. // optimize memory usage.
  376. BOOL CSharedBlksMem::__FindFreeNode(SMEM& me, DWORD nBytes, int& ListIndex)
  377. {
  378. static FncCnt;
  379. ++FncCnt;
  380. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  381. VIRTUAL_FREE_MEM_NODE_HDR *pNode = NULL;
  382. for(;!pNode && (ListIndex < SMEM_NUM_BLK_SIZES); ListIndex++)
  383. {
  384. if ((pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pSuper->FreeTable[ListIndex])) != NULL)
  385. {
  386. DWORD blk_num = pSuper->FreeTable[ListIndex].blk;
  387. while(pNode)
  388. {
  389. DWORD RealLen = GetNodeDataLen((VIRTUAL_MEM_NODE_HDR *)pNode);
  390. if (RealLen >= nBytes)
  391. {
  392. me = Smem(pNode, blk_num);
  393. return __AllocNode(pNode, me, nBytes + sizeof(VIRTUAL_MEM_NODE_HDR), ListIndex);
  394. }
  395. // Try next
  396. blk_num = pNode->nextfree.blk;
  397. pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->nextfree);
  398. }
  399. }
  400. }
  401. return FALSE;
  402. }
  403. // No free nodes available. Try to allocate a new segment
  404. BOOL CSharedBlksMem::__AllocNewNode(SMEM& me, DWORD nBytes, int& ListIndex)
  405. {
  406. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  407. if (!AllocSegment(pSuper->NumUsedSegments))
  408. return FALSE;
  409. return __FindFreeNode(me, nBytes, ListIndex);
  410. }
  411. void CSharedBlksMem::Rescan()
  412. {
  413. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  414. ASSERT(m_Blks[0] != NULL);
  415. for(DWORD Index = 0; Index < pSuper->NumUsedSegments; Index++)
  416. {
  417. if (!m_Blks[Index])
  418. AllocSegment(Index);
  419. }
  420. }
  421. // Allocate the free node.
  422. // nBytes = buffersize + header
  423. BOOL CSharedBlksMem::__AllocNode(VIRTUAL_FREE_MEM_NODE_HDR *pNode, SMEM& me, DWORD nBytes, int ListIndex)
  424. {
  425. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  426. ASSERT(pNode->node_hdr.isfree == TRUE);
  427. // See if we have to split the node
  428. if ((pNode->node_hdr.size - nBytes) >= (SMEM_NUM_BLK_SIZES_BASE + sizeof(VIRTUAL_MEM_NODE_HDR)))
  429. {
  430. // Split it.
  431. __CreateNewNode(
  432. me.blk, 
  433. pNode, 
  434. (VIRTUAL_FREE_MEM_NODE_HDR *)((char *)pNode + nBytes), 
  435. pNode->node_hdr.size - nBytes,
  436. pNode->node_hdr.hasnext);
  437. pNode->node_hdr.size = nBytes;
  438. }
  439. pSuper->UsedNodes++;
  440. pSuper->UserMemory += (nBytes - sizeof(VIRTUAL_MEM_NODE_HDR));
  441. pSuper->PhysMemory += nBytes;
  442. __UnlinkFree(ListIndex, me);
  443. return TRUE;
  444. }
  445. // Create a new (free) node at a location. The location is verified OK.
  446. void CSharedBlksMem::__CreateNewNode(
  447.  DWORD Segment,
  448.  VIRTUAL_FREE_MEM_NODE_HDR *pPrevNode, 
  449.  VIRTUAL_FREE_MEM_NODE_HDR *pNode, 
  450.  DWORD nBytes,
  451.  BOOL HasNext)
  452. {
  453. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  454. pSuper->NumNodes++;
  455. pNode->node_hdr.isfree = TRUE;
  456. pNode->node_hdr.hasnext = HasNext;
  457. pNode->node_hdr.size = nBytes;
  458. SMEM me = Smem(pNode, Segment);
  459. if (pPrevNode)
  460. {
  461. SMEM sPrev = Smem(pPrevNode, Segment);
  462. pNode->node_hdr.prev = sPrev;
  463. }
  464. else
  465. {
  466. pNode->node_hdr.prev = 0;
  467. }
  468. #ifdef _DEBUG
  469. memcpy(pNode->node_hdr.watermark, tag_FreeWatermark, sizeof(tag_FreeWatermark));
  470. #endif
  471. if (HasNext)
  472. {
  473. VIRTUAL_MEM_NODE_HDR *pNext = (VIRTUAL_MEM_NODE_HDR *)((char *)pNode) + nBytes;
  474. pNext->prev = me;
  475. }
  476. // Link it to the list
  477. __LinkFree(me.blk, pNode);
  478. }
  479. #ifdef _DEBUG
  480. LPVOID CSharedBlksMem::__dbg__Ptr(SMEM sm)
  481. {
  482. if (!m_Blks[sm.blk]) Rescan();
  483. VIRTUAL_MEM_NODE_HDR *phdr = ((int)sm) ? (VIRTUAL_MEM_NODE_HDR *)(((char *)m_Blks[sm.blk]) + sm.ofs) : NULL;
  484. LPSTR p = (LPSTR)phdr;
  485. AssertValidFreeTables();
  486. if (phdr)
  487. {
  488. ASSERT(AfxIsValidAddress(phdr, sizeof(VIRTUAL_MEM_NODE_HDR)));
  489. ASSERT(memcmp(phdr->watermark, tag_UsedWatermark, sizeof(tag_UsedWatermark)) == 0);
  490. p += sizeof(VIRTUAL_MEM_NODE_HDR);
  491. }
  492. return p;
  493. }
  494. #endif
  495. #if SMEM_DEBUG
  496. // Diagnostic functions
  497. void CSharedBlksMem::AssertValidFreeTables()
  498. {
  499. SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
  500. VIRTUAL_FREE_MEM_NODE_HDR *pNode;
  501. for(int ListIndex = 0; ListIndex < SMEM_NUM_BLK_SIZES; ListIndex++)
  502. {
  503. if ((pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pSuper->FreeTable[ListIndex])) != NULL)
  504. {
  505. while(pNode)
  506. {
  507. ASSERT(pNode->node_hdr.isfree == TRUE);
  508. ASSERT(ListIndex == pNode->index);
  509. ASSERT(ListIndex >= GetLenIndex(&pNode->node_hdr));
  510. pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->nextfree);
  511. }
  512. }
  513. }
  514. }
  515. #endif
  516. ///////////////////////////////////////////////////////////////////////////
  517. // Thread synchronization
  518. //*****************************************************************************************
  519. //           Implementation of the Reader/Writer lock solution                           
  520. // From http://www.microsoft.com/win32dev/base/locktest.htm
  521. // Reworked by jgaa to support multiple processes     
  522. //*****************************************************************************************
  523. CRWLock::CRWLock()
  524. {
  525. hMutex = NULL;
  526. hWriterMutex = NULL;
  527. hReaderEvent = NULL;
  528. pCounter = NULL;
  529. }
  530. CRWLock::~CRWLock()
  531. if (hReaderEvent)
  532. CloseHandle(hReaderEvent);
  533. if (hMutex)
  534. CloseHandle(hMutex);
  535. if (hWriterMutex)
  536. CloseHandle(hWriterMutex);
  537. }
  538. HANDLE CRWLock::OpenEvent(LPCSTR Name, BOOL bManualReset, BOOL bInitialState)
  539. {
  540. HANDLE h = ::CreateEvent(NULL,bManualReset,bInitialState,Name);
  541. if ((h == NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))
  542. h = ::OpenEvent(EVENT_ALL_ACCESS,FALSE,Name);
  543. return h;
  544. }
  545. HANDLE CRWLock::OpenMutex(LPCSTR Name)
  546. {
  547. HANDLE h = ::CreateMutex(NULL,FALSE,Name);
  548. if ((h == NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))
  549. h = ::OpenMutex(NULL,FALSE,Name);
  550. return h;
  551. }
  552. CRWLock::Create(LPCSTR Name)
  553. CGlobalLock Lock(CatStr(Name, "glblk"));
  554.   if ((hReaderEvent=OpenEvent(CatStr(Name, "rev"), TRUE, FALSE)) == NULL)
  555. return FALSE;
  556.   if ((hMutex = OpenEvent(CatStr(Name, "mx"), FALSE, TRUE)) == NULL)
  557. return FALSE;
  558.   if ((hWriterMutex = OpenMutex(CatStr(Name, "wmx"))) == NULL)
  559. return FALSE;
  560. // Get shared memory
  561. if (SMemSeg.Create(CatStr(Name, "smem"), sizeof(CWRLOCK_SMHDR), TRUE) == NULL)
  562. return FALSE;
  563. CWRLOCK_SMHDR *pMemPtr = (CWRLOCK_SMHDR *)SMemSeg.GetDataPtr();
  564. pCounter = &pMemPtr->Counter;
  565. if (pMemPtr->IsInitialized == FALSE)
  566. {
  567. pMemPtr->IsInitialized = TRUE;
  568. pMemPtr->Counter = -1;
  569. }
  570. return TRUE;
  571. }
  572. void CRWLock::Claim(int i)
  573. if (i== WRITER)
  574. {  
  575. WaitForSingleObject(hWriterMutex,INFINITE);
  576. WaitForSingleObject(hMutex, INFINITE);
  577. }
  578. else
  579. {   
  580. if (InterlockedIncrement(pCounter) == 0)
  581. WaitForSingleObject(hMutex, INFINITE);
  582. SetEvent(hReaderEvent);
  583. }
  584. WaitForSingleObject(hReaderEvent,INFINITE);
  585. }
  586. }
  587. void CRWLock::Release(int i)
  588. if (i == WRITER)
  589. SetEvent(hMutex);
  590. ReleaseMutex(hWriterMutex);
  591. }
  592. else if (InterlockedDecrement(pCounter) < 0)
  593. ResetEvent(hReaderEvent);
  594. SetEvent(hMutex);
  595. }
  596. }
  597. CString CRWLock::CatStr(LPCSTR Name, LPCSTR ext)
  598. {
  599. CString cBuf = Name;
  600. cBuf += ext;
  601. return cBuf;
  602. }