WarSMemory.cpp
资源名称:warftpd.zip [点击查看]
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:19k
源码类别:
Ftp客户端
开发平台:
Visual C++
- // See the "War Software Series License Agreement" for details concerning
- // use and distribution.
- // ---
- // This source code, executables and programs containing source code or
- // binaries or proprietetary technology from the War Software Series are
- // NOT alloed used, viewed or tested by any governmental agencies in
- // any countries. This includes the government, departments, police,
- // military etc.
- // ---
- // This file is intended for use with Tab space = 2
- // Created and maintained in MSVC Developer Studio
- // ---
- // NAME : WarSMemory.cpp
- // PURPOSE : Shared memory management and thread/process synchronization
- // PROGRAM :
- // DATE : March 9 1997
- // AUTHOR : Jarle Aase
- // ---
- //
- // REVISION HISTORY
- //
- // Extended logging and testing from shared memory submodule
- #define SMEM_DEBUG 0
- #include "stdafx.h"
- #include "WarSoftware.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- ////////////////////////////////////////////////////////////////////////////////////
- // CGlobalLock
- CGlobalLock::CGlobalLock(LPCSTR Name)
- {
- m_pSemaphore = new CSemaphore(1, 1, Name);
- m_pSligleLock = new CSingleLock(m_pSemaphore);
- m_pSligleLock->Lock();
- }
- CGlobalLock::~CGlobalLock()
- {
- m_pSligleLock->Unlock();
- delete m_pSligleLock;
- delete m_pSemaphore;
- }
- ////////////////////////////////////////////////////////////////////////////////////
- // CSharedMemSegment
- #ifdef _DEBUG
- const unsigned short CSharedBlksMem::tag_FreeWatermark[4] = {0xfeee, 0xfeee, 0xfeee, 0xfeee};
- const unsigned short CSharedBlksMem::tag_UsedWatermark[4] = {0,0,0,0};
- #endif
- CSharedMemSegment::CSharedMemSegment()
- {
- m_Name = "** Not initialized ***";
- m_hMMFile = NULL;
- m_Size = 0;
- m_pSMH = NULL;
- #if SMEM_DEBUG
- CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedMemSegment(%08x) - New segment allocated.", (DWORD)this);
- #endif
- }
- CSharedMemSegment::~CSharedMemSegment()
- {
- if (m_hMMFile)
- CloseHandle(m_hMMFile);
- m_hMMFile = NULL;
- #if SMEM_DEBUG
- CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM ~CSharedMemSegment(%08x) - segment deleted.", (DWORD)this);
- #endif
- }
- LPVOID CSharedMemSegment::Create(LPCSTR Name, DWORD Size, BOOL KeepInMemory)
- {
- CGlobalLock Lock(LNAME_SHARED_MEM_SEGMENT);
- #if SMEM_DEBUG
- CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedMemSegment::Create(%08x) - creating %s (%d bytes)",
- (DWORD)this, Name, Size);
- #endif
- BOOL WeMustInitialize = FALSE;
- if (!(m_hMMFile = OpenFileMapping (FILE_MAP_WRITE,
- FALSE,
- Name)))
- {
- if (!(m_hMMFile = CreateFileMapping ((HANDLE)0xFFFFFFFF,
- NULL,
- PAGE_READWRITE | SEC_COMMIT | (KeepInMemory ? SEC_NOCACHE : 0) ,
- 0,
- (m_Size = Size) + sizeof(SHARED_MEM_SEG_HDR),
- Name)))
- return NULL;
- WeMustInitialize = TRUE;
- }
- LPVOID __hdr__Ptr = MapViewOfFile(m_hMMFile, FILE_MAP_WRITE, 0,0,0);
- if (!__hdr__Ptr)
- {
- CloseHandle(m_hMMFile);
- m_hMMFile = NULL;
- return NULL;
- }
- m_pSMH = (SHARED_MEM_SEG_HDR *)__hdr__Ptr;
- if (WeMustInitialize)
- {
- memset(__hdr__Ptr, 0, Size + sizeof(SHARED_MEM_SEG_HDR));
- m_pSMH->Size = Size + sizeof(SHARED_MEM_SEG_HDR);
- m_pSMH->AccessCnt = 0;
- strcpy(m_pSMH->Name, Name);
- for(int i = 0; i < SHMEM_NUM_USER_PTRS; i++)
- m_pSMH->pUserPtr[i] = NULL;
- }
- if (m_pSMH->Size != (Size + sizeof(SHARED_MEM_SEG_HDR)))
- {
- CloseHandle(m_hMMFile);
- m_hMMFile = NULL;
- return NULL;
- }
- m_pSMH->AccessCnt++;
- return (char *)GetDataPtr();
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- // CSharedBlksMem
- CSharedBlksMem::CSharedBlksMem()
- {
- m_Mutex = NULL;
- memset(m_Blks, 0, sizeof(m_Blks));
- m_Name = "";
- m_SegmentSize = 0;
- m_IsInitialized = FALSE;
- #if SMEM_DEBUG
- CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedBlksMem(%08x) - created",
- (DWORD)this);
- #endif
- }
- CSharedBlksMem::~CSharedBlksMem()
- {
- if (m_Mutex != NULL)
- CloseHandle(m_Mutex);
- #if SMEM_DEBUG
- CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM ~CSharedBlksMem(%08x) - destroyed",
- (DWORD)this);
- #endif
- }
- BOOL CSharedBlksMem::Create(LPCSTR Name, DWORD BlkSize)
- {
- ASSERT(m_IsInitialized == FALSE); // Only initialize once
- m_Name = Name;
- m_SegmentSize = BlkSize;
- #if SMEM_DEBUG
- CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedBlksMem::Create(%08x) - creating %s (%d bytes)",
- (DWORD)this, Name, BlkSize);
- #endif
- if (!Initialize())
- return FALSE;
- if (!AllocSegment(0))
- return FALSE;
- return TRUE;
- }
- // Initialize mutex and (eventually) super block
- BOOL CSharedBlksMem::Initialize()
- {
- ASSERT(m_IsInitialized == FALSE); // Only initialize once
- CGlobalLock Lock(LNAME_SHARED_MEM_SEGMENT);
- m_IsInitialized = TRUE;
- if ((m_Mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, SHMEM_BLKS_MUTEX_NAME)) == NULL)
- m_Mutex = CreateMutex(NULL, FALSE, SHMEM_BLKS_MUTEX_NAME);
- return m_Mutex != NULL;
- }
- //
- BOOL CSharedBlksMem::AllocSegment(int Index)
- {
- BOOL Rval;
- #if SMEM_DEBUG
- CLog::GetLog()->LogMsg(LOGF_DEBUG,"SMEM CSharedBlksMem::AllocSegment() - Allocating (Index = %d)",
- Index);
- #endif
- if (Index >= SHARED_MEM_MAX_BLKS)
- {
- CLog::GetLog()->LogMsg(LOGF_WARNINGS,
- "CSharedBlksMem::AllocSegment() - Out of memory. %d segments, each %d bytes are in use",
- SHARED_MEM_MAX_BLKS, m_SegmentSize);
- CLog::GetLog()->LogMsg(LOGF_WARNINGS,
- "CSharedBlksMem::AllocSegment() - You should increase the segment size.",
- SHARED_MEM_MAX_BLKS, m_SegmentSize);
- return FALSE; // Out of memory
- }
- WaitForSingleObject(m_Mutex, INFINITE);
- ASSERT(m_Blks[Index] == NULL);
- CString SegName;
- SegName.Format("%s%d", m_Name, Index);
- Rval = (m_Blks[Index] = m_Segments[Index].Create(SegName, m_SegmentSize)) != NULL;
- if (Rval)
- {
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- SUPER_MEM_BLKS_HDR *pBlkHdr = (SUPER_MEM_BLKS_HDR *)m_Blks[Index];
- SHARED_MEM_SEG_HDR *pSegHdr = m_Segments[Index].m_pSMH;
- if (!pBlkHdr->IsInitialized)
- {
- pSuper->NumUsedSegments++;
- pBlkHdr->PhysMemory = sizeof(SUPER_MEM_BLKS_HDR);
- pBlkHdr->IsInitialized = TRUE;
- pBlkHdr->SegmentSize = pSegHdr->Size - sizeof(SHARED_MEM_SEG_HDR);
- // Add one free node at the size of the entire segment
- VIRTUAL_FREE_MEM_NODE_HDR *pNode
- = (VIRTUAL_FREE_MEM_NODE_HDR *)(((char *)m_Blks[Index]) + sizeof(SUPER_MEM_BLKS_HDR));
- pNode->node_hdr.isfree = TRUE;
- pNode->node_hdr.hasnext = FALSE;
- pNode->node_hdr.size = pBlkHdr->SegmentSize - sizeof(SUPER_MEM_BLKS_HDR);
- pNode->node_hdr.prev = 0;
- pNode->nextfree = 0;
- // Link it to the list
- __LinkFree(Index, pNode);
- }
- }
- ReleaseMutex(m_Mutex);
- return Rval;
- }
- // Link a free node to the first entry in the appropriate free list.
- void CSharedBlksMem::__LinkFree(int Segment, VIRTUAL_FREE_MEM_NODE_HDR *pNode)
- {
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- VIRTUAL_FREE_MEM_NODE_HDR *pLink;
- int LenIndex = GetLenIndex(&pNode->node_hdr);
- SMEM me = Smem(pNode, Segment);
- // Always link as first
- pLink = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pSuper->FreeTable[LenIndex]);
- pNode->prevfree = 0;
- pNode->index = LenIndex;
- #ifdef _DEBUG
- // Link free
- memcpy(pNode->node_hdr.watermark, tag_FreeWatermark, sizeof(tag_FreeWatermark));
- #endif
- if (pLink)
- {
- pNode->nextfree = pSuper->FreeTable[LenIndex];
- pLink->prevfree = me;
- }
- else
- {
- pNode->nextfree = 0;
- }
- pNode->node_hdr.isfree = TRUE;
- pSuper->FreeTable[LenIndex] = me;
- }
- // Unlink a node from the free chain
- void CSharedBlksMem::__UnlinkFree(int ListIndex, SMEM me)
- {
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- VIRTUAL_FREE_MEM_NODE_HDR *pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(me);
- VIRTUAL_FREE_MEM_NODE_HDR *pRootNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pSuper->FreeTable[ListIndex]);
- VIRTUAL_FREE_MEM_NODE_HDR *pPrevNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->prevfree);
- VIRTUAL_FREE_MEM_NODE_HDR *pNextNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->nextfree);
- if (!pPrevNode)
- {
- // Root
- pSuper->FreeTable[ListIndex] = pNode->nextfree;
- }
- else
- {
- pPrevNode->nextfree = pNode->nextfree;
- }
- if (pNextNode)
- pNextNode->prevfree = pNode->prevfree;
- #ifdef _DEBUG
- // Tag as used
- ASSERT(memcmp(pNode->node_hdr.watermark, tag_FreeWatermark, sizeof(tag_FreeWatermark)) == 0);
- memcpy(pNode->node_hdr.watermark, tag_UsedWatermark, sizeof(tag_UsedWatermark));
- ASSERT(pNode->node_hdr.isfree == TRUE);
- #endif
- pNode->node_hdr.isfree = FALSE;
- }
- // Return the free list index of the node, based on it's size
- // There are SMEM_NUM_BLK_SIZES lists of free nodes, each with
- // free sizes <= the desired size (physical size - header)
- int CSharedBlksMem::GetLenIndex(VIRTUAL_MEM_NODE_HDR *pNode)
- {
- return GetLenIndex(GetNodeDataLen(pNode));
- }
- int CSharedBlksMem::GetLenIndex(int MinSize)
- {
- static int SizeTable[SMEM_NUM_BLK_SIZES];
- if (SizeTable[0] == 0)
- {
- // Initialize
- int val = SMEM_NUM_BLK_SIZES_BASE;
- for(int Index = 0; Index < (SMEM_NUM_BLK_SIZES -1); Index ++)
- {
- SizeTable[Index] = val;
- val *= 2;
- }
- SizeTable[SMEM_NUM_BLK_SIZES -1] = 0xffffff; // Max 24 bit value
- }
- for(int Index = 0; Index < (SMEM_NUM_BLK_SIZES -1); Index ++)
- {
- if (SizeTable[Index] >= MinSize)
- break;
- }
- return Index;
- }
- BOOL CSharedBlksMem::sh_malloc(SMEM& me, DWORD nBytes)
- {
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- me = 0;
- BOOL Rval = FALSE;
- if (nBytes >= (pSuper->SegmentSize - sizeof(SUPER_MEM_BLKS_HDR)))
- {
- CLog::GetLog()->LogMsg(LOGF_WARNINGS,
- "CSharedBlksMem::sh_malloc() - %d bytes requested, segment size is %d bytes(avail). Increase segment size.",
- nBytes, pSuper->SegmentSize - sizeof(SUPER_MEM_BLKS_HDR));
- return FALSE;
- }
- int ListIndex = GetLenIndex(nBytes);
- WaitForSingleObject(m_Mutex, INFINITE);
- AssertValidFreeTables();
- Rescan();
- if ((Rval = __FindFreeNode(me, nBytes, ListIndex)) == FALSE)
- Rval = __AllocNewNode(me, nBytes, ListIndex);
- AssertValidFreeTables();
- ReleaseMutex(m_Mutex);
- return Rval;
- }
- BOOL CSharedBlksMem::sh_realloc(SMEM& shm, DWORD nBytes)
- {
- SMEM new_mem;
- if (sh_malloc(new_mem, nBytes))
- {
- VIRTUAL_MEM_NODE_HDR *pNode = __hdr__Ptr(shm);
- VIRTUAL_MEM_NODE_HDR *pNewNode = __hdr__Ptr(new_mem);
- memcpy(pNewNode, pNode, min(nBytes, pNode->size));
- sh_free(shm);
- shm = new_mem;
- return TRUE;
- }
- return FALSE;
- }
- void CSharedBlksMem::sh_free(SMEM shm)
- {
- WaitForSingleObject(m_Mutex, INFINITE);
- AssertValidFreeTables();
- VIRTUAL_FREE_MEM_NODE_HDR *pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(shm);
- VIRTUAL_FREE_MEM_NODE_HDR *pPrev = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->node_hdr.prev);
- VIRTUAL_FREE_MEM_NODE_HDR *pNext = (VIRTUAL_FREE_MEM_NODE_HDR *)((char *)pNode) + pNode->node_hdr.size;
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- pSuper->UserMemory -= (pNode->node_hdr.size - sizeof(VIRTUAL_MEM_NODE_HDR));
- pSuper->PhysMemory -= pNode->node_hdr.size;
- BOOL HasNext = pNode->node_hdr.hasnext;
- // See if prev node is free, and withing the same segment. If it is, merge the two nodes.
- if (pPrev && pPrev->node_hdr.isfree && (pNode->node_hdr.prev.blk == shm.blk))
- {
- pPrev->node_hdr.size += pNode->node_hdr.size;
- pSuper->NumNodes--;
- pNode = pPrev;
- __UnlinkFree(pNode->index, Smem(pPrev, shm.blk));
- }
- // See if next node is free. If it is, merge the two nodes.
- if (HasNext)
- {
- if (pNext->node_hdr.isfree)
- {
- ASSERT(pNext->node_hdr.prev == shm);
- pNode->node_hdr.size += pNext->node_hdr.size;
- pSuper->NumNodes--;
- __UnlinkFree(pNext->index, Smem(pNext, shm.blk));
- }
- }
- pSuper->NumNodes--;
- // Link it
- __LinkFree(shm.blk, pNode);
- AssertValidFreeTables();
- ReleaseMutex(m_Mutex);
- }
- // Try to find (and take) a free node
- // This function will perform a sequentional scan for a
- // node that fit on the free node linked list where a node of
- // the required size _might_ exist. If we looked at the next
- // free list index, all nodes will fit, but this will result
- // in more memory fragmentation.
- // The current implementation use a little more CPU to
- // optimize memory usage.
- BOOL CSharedBlksMem::__FindFreeNode(SMEM& me, DWORD nBytes, int& ListIndex)
- {
- static FncCnt;
- ++FncCnt;
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- VIRTUAL_FREE_MEM_NODE_HDR *pNode = NULL;
- for(;!pNode && (ListIndex < SMEM_NUM_BLK_SIZES); ListIndex++)
- {
- if ((pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pSuper->FreeTable[ListIndex])) != NULL)
- {
- DWORD blk_num = pSuper->FreeTable[ListIndex].blk;
- while(pNode)
- {
- DWORD RealLen = GetNodeDataLen((VIRTUAL_MEM_NODE_HDR *)pNode);
- if (RealLen >= nBytes)
- {
- me = Smem(pNode, blk_num);
- return __AllocNode(pNode, me, nBytes + sizeof(VIRTUAL_MEM_NODE_HDR), ListIndex);
- }
- // Try next
- blk_num = pNode->nextfree.blk;
- pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->nextfree);
- }
- }
- }
- return FALSE;
- }
- // No free nodes available. Try to allocate a new segment
- BOOL CSharedBlksMem::__AllocNewNode(SMEM& me, DWORD nBytes, int& ListIndex)
- {
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- if (!AllocSegment(pSuper->NumUsedSegments))
- return FALSE;
- return __FindFreeNode(me, nBytes, ListIndex);
- }
- void CSharedBlksMem::Rescan()
- {
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- ASSERT(m_Blks[0] != NULL);
- for(DWORD Index = 0; Index < pSuper->NumUsedSegments; Index++)
- {
- if (!m_Blks[Index])
- AllocSegment(Index);
- }
- }
- // Allocate the free node.
- // nBytes = buffersize + header
- BOOL CSharedBlksMem::__AllocNode(VIRTUAL_FREE_MEM_NODE_HDR *pNode, SMEM& me, DWORD nBytes, int ListIndex)
- {
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- ASSERT(pNode->node_hdr.isfree == TRUE);
- // See if we have to split the node
- if ((pNode->node_hdr.size - nBytes) >= (SMEM_NUM_BLK_SIZES_BASE + sizeof(VIRTUAL_MEM_NODE_HDR)))
- {
- // Split it.
- __CreateNewNode(
- me.blk,
- pNode,
- (VIRTUAL_FREE_MEM_NODE_HDR *)((char *)pNode + nBytes),
- pNode->node_hdr.size - nBytes,
- pNode->node_hdr.hasnext);
- pNode->node_hdr.size = nBytes;
- }
- pSuper->UsedNodes++;
- pSuper->UserMemory += (nBytes - sizeof(VIRTUAL_MEM_NODE_HDR));
- pSuper->PhysMemory += nBytes;
- __UnlinkFree(ListIndex, me);
- return TRUE;
- }
- // Create a new (free) node at a location. The location is verified OK.
- void CSharedBlksMem::__CreateNewNode(
- DWORD Segment,
- VIRTUAL_FREE_MEM_NODE_HDR *pPrevNode,
- VIRTUAL_FREE_MEM_NODE_HDR *pNode,
- DWORD nBytes,
- BOOL HasNext)
- {
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- pSuper->NumNodes++;
- pNode->node_hdr.isfree = TRUE;
- pNode->node_hdr.hasnext = HasNext;
- pNode->node_hdr.size = nBytes;
- SMEM me = Smem(pNode, Segment);
- if (pPrevNode)
- {
- SMEM sPrev = Smem(pPrevNode, Segment);
- pNode->node_hdr.prev = sPrev;
- }
- else
- {
- pNode->node_hdr.prev = 0;
- }
- #ifdef _DEBUG
- memcpy(pNode->node_hdr.watermark, tag_FreeWatermark, sizeof(tag_FreeWatermark));
- #endif
- if (HasNext)
- {
- VIRTUAL_MEM_NODE_HDR *pNext = (VIRTUAL_MEM_NODE_HDR *)((char *)pNode) + nBytes;
- pNext->prev = me;
- }
- // Link it to the list
- __LinkFree(me.blk, pNode);
- }
- #ifdef _DEBUG
- LPVOID CSharedBlksMem::__dbg__Ptr(SMEM sm)
- {
- if (!m_Blks[sm.blk]) Rescan();
- VIRTUAL_MEM_NODE_HDR *phdr = ((int)sm) ? (VIRTUAL_MEM_NODE_HDR *)(((char *)m_Blks[sm.blk]) + sm.ofs) : NULL;
- LPSTR p = (LPSTR)phdr;
- AssertValidFreeTables();
- if (phdr)
- {
- ASSERT(AfxIsValidAddress(phdr, sizeof(VIRTUAL_MEM_NODE_HDR)));
- ASSERT(memcmp(phdr->watermark, tag_UsedWatermark, sizeof(tag_UsedWatermark)) == 0);
- p += sizeof(VIRTUAL_MEM_NODE_HDR);
- }
- return p;
- }
- #endif
- #if SMEM_DEBUG
- // Diagnostic functions
- void CSharedBlksMem::AssertValidFreeTables()
- {
- SUPER_MEM_BLKS_HDR *pSuper = (SUPER_MEM_BLKS_HDR *)m_Blks[0];
- VIRTUAL_FREE_MEM_NODE_HDR *pNode;
- for(int ListIndex = 0; ListIndex < SMEM_NUM_BLK_SIZES; ListIndex++)
- {
- if ((pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pSuper->FreeTable[ListIndex])) != NULL)
- {
- while(pNode)
- {
- ASSERT(pNode->node_hdr.isfree == TRUE);
- ASSERT(ListIndex == pNode->index);
- ASSERT(ListIndex >= GetLenIndex(&pNode->node_hdr));
- pNode = (VIRTUAL_FREE_MEM_NODE_HDR *)__hdr__Ptr(pNode->nextfree);
- }
- }
- }
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////
- // Thread synchronization
- //*****************************************************************************************
- // Implementation of the Reader/Writer lock solution
- // From http://www.microsoft.com/win32dev/base/locktest.htm
- // Reworked by jgaa to support multiple processes
- //*****************************************************************************************
- CRWLock::CRWLock()
- {
- hMutex = NULL;
- hWriterMutex = NULL;
- hReaderEvent = NULL;
- pCounter = NULL;
- }
- CRWLock::~CRWLock()
- {
- if (hReaderEvent)
- CloseHandle(hReaderEvent);
- if (hMutex)
- CloseHandle(hMutex);
- if (hWriterMutex)
- CloseHandle(hWriterMutex);
- }
- HANDLE CRWLock::OpenEvent(LPCSTR Name, BOOL bManualReset, BOOL bInitialState)
- {
- HANDLE h = ::CreateEvent(NULL,bManualReset,bInitialState,Name);
- if ((h == NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))
- h = ::OpenEvent(EVENT_ALL_ACCESS,FALSE,Name);
- return h;
- }
- HANDLE CRWLock::OpenMutex(LPCSTR Name)
- {
- HANDLE h = ::CreateMutex(NULL,FALSE,Name);
- if ((h == NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))
- h = ::OpenMutex(NULL,FALSE,Name);
- return h;
- }
- CRWLock::Create(LPCSTR Name)
- {
- CGlobalLock Lock(CatStr(Name, "glblk"));
- if ((hReaderEvent=OpenEvent(CatStr(Name, "rev"), TRUE, FALSE)) == NULL)
- return FALSE;
- if ((hMutex = OpenEvent(CatStr(Name, "mx"), FALSE, TRUE)) == NULL)
- return FALSE;
- if ((hWriterMutex = OpenMutex(CatStr(Name, "wmx"))) == NULL)
- return FALSE;
- // Get shared memory
- if (SMemSeg.Create(CatStr(Name, "smem"), sizeof(CWRLOCK_SMHDR), TRUE) == NULL)
- return FALSE;
- CWRLOCK_SMHDR *pMemPtr = (CWRLOCK_SMHDR *)SMemSeg.GetDataPtr();
- pCounter = &pMemPtr->Counter;
- if (pMemPtr->IsInitialized == FALSE)
- {
- pMemPtr->IsInitialized = TRUE;
- pMemPtr->Counter = -1;
- }
- return TRUE;
- }
- void CRWLock::Claim(int i)
- {
- if (i== WRITER)
- {
- WaitForSingleObject(hWriterMutex,INFINITE);
- WaitForSingleObject(hMutex, INFINITE);
- }
- else
- {
- if (InterlockedIncrement(pCounter) == 0)
- {
- WaitForSingleObject(hMutex, INFINITE);
- SetEvent(hReaderEvent);
- }
- WaitForSingleObject(hReaderEvent,INFINITE);
- }
- }
- void CRWLock::Release(int i)
- {
- if (i == WRITER)
- {
- SetEvent(hMutex);
- ReleaseMutex(hWriterMutex);
- }
- else if (InterlockedDecrement(pCounter) < 0)
- {
- ResetEvent(hReaderEvent);
- SetEvent(hMutex);
- }
- }
- CString CRWLock::CatStr(LPCSTR Name, LPCSTR ext)
- {
- CString cBuf = Name;
- cBuf += ext;
- return cBuf;
- }