⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unixsharedmemory.cpp

📁 "More for C++" is a class library that provides some features that are usually common for object ori
💻 CPP
字号:
////  This file is part of the "More for C++" library////  Copyright (c) 1999-2003 by Thorsten Goertz (thorsten@morefor.org)////  The "More for C++" library is free software; you can redistribute it and/or//  modify it under the terms of the license that comes with this package.////  Read "license.txt" for more details.////  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED//  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES//  OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.////////////////////////////////////////////////////////////////////////////////#include <more/string.hpp>#include "unixsharedmemory.hpp"using namespace more;using namespace more::os;using namespace more::os::unix_;typedef unsigned char byte;////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::Object(  size_t  nRootKey,  size_t  nObjectSize){  m_pChunkHeader = createChunk( nRootKey, nObjectSize, m_nSegmentId, m_nChunkOffset );}////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::Object(  const String& sObjectId): m_pChunkHeader( 0 ){  Array<String> splittedId = sObjectId.split( ',' );  if( splittedId.getLength( ) == 2 )  {    splittedId[0].to( m_nSegmentId );    splittedId[1].to( m_nChunkOffset );    m_pChunkHeader = retrieveChunk( m_nSegmentId, m_nChunkOffset );  }}////////////////////////////////////////////////////////////////////////////////void UnixSharedMemory::Object::finalize( ){}////////////////////////////////////////////////////////////////////////////////bool UnixSharedMemory::Object::isValid( ) const{  return m_pChunkHeader != 0;}////////////////////////////////////////////////////////////////////////////////String UnixSharedMemory::Object::getId( ) const{  String sResult;  if( isValid( ) )  {    sResult = String::from( m_nSegmentId ) + ',' + String::from( m_nChunkOffset );  }  return sResult;}////////////////////////////////////////////////////////////////////////////////size_t UnixSharedMemory::Object::getSize( ) const{  size_t nResult = 0;  if( isValid( ) )  {    nResult = m_pChunkHeader -> m_nObjectSize;  }  return nResult;}////////////////////////////////////////////////////////////////////////////////void* UnixSharedMemory::Object::getData( ) const{  void* pResult = 0;  if( isValid( ) )  {    pResult = ( m_pChunkHeader + 1 );  }  return pResult;}////////////////////////////////////////////////////////////////////////////////void UnixSharedMemory::Object::destroy( ){  if( isValid( ) )  {    m_pChunkHeader -> m_bInUse = false;    m_pChunkHeader -> m_nObjectSize = 0;    m_pChunkHeader = 0;    joinChunks( retrieveSegment( m_nSegmentId ) );  }}////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::ChunkHeader* UnixSharedMemory::Object::createChunk(  size_t    nRootKey,  size_t    nObjectSize,  int&      rnSegmentId,  size_t&   rnChunkOffset){  ChunkHeader*    pResult = 0;  SegmentHeader*  pSegmentHeader = 0;  SegmentHeader*  pPreviousSegmentHeader = 0;  pSegmentHeader = retrieveSegment( nRootKey, rnSegmentId );  while( pResult == 0 && pSegmentHeader != 0 )  {    pResult = allocateChunk( pSegmentHeader, nObjectSize, rnChunkOffset );    if( pResult == 0 )    {      pPreviousSegmentHeader = pSegmentHeader;      pSegmentHeader = retrieveSegment( pSegmentHeader -> m_nNextSegment );    }  }  if( pResult == 0 )  {    if( pPreviousSegmentHeader == 0 )    {      pSegmentHeader = createSegment( nRootKey, 0, sizeof( ChunkHeader ) + nObjectSize, rnSegmentId );    }    else    {      pSegmentHeader = createSegment( 0, pPreviousSegmentHeader, sizeof( ChunkHeader ) + nObjectSize, rnSegmentId );    }    if( pSegmentHeader != 0 )    {      pResult = allocateChunk( pSegmentHeader, nObjectSize, rnChunkOffset );    }  }  return pResult;}////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::ChunkHeader* UnixSharedMemory::Object::allocateChunk(  SegmentHeader*  pSegmentHeader,  size_t          nObjectSize,  size_t&         rnChunkOffset){  ChunkHeader*  pResult = 0;  size_t        nOffset = 0;  size_t        nMaxOffset = pSegmentHeader -> m_nSize - sizeof( SegmentHeader );  byte*         pBytes = ( byte* ) ( pSegmentHeader + 1 );  while( pResult == 0 && nOffset < nMaxOffset )  {    ChunkHeader* pChunkHeader = ( ChunkHeader* ) ( pBytes + nOffset );    if( pChunkHeader -> m_bInUse || sizeof( ChunkHeader ) + nObjectSize > pChunkHeader -> m_nChunkSize )    {      nOffset += pChunkHeader -> m_nChunkSize;    }    else    {      pResult = splitChunk( pChunkHeader, nObjectSize );      pResult -> m_bInUse = true;      pResult -> m_nObjectSize = nObjectSize;      if( pResult == pChunkHeader )      {        rnChunkOffset = nOffset;      }      else      {        rnChunkOffset = nOffset + pChunkHeader -> m_nChunkSize;      }    }  }  return pResult;}////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::ChunkHeader* UnixSharedMemory::Object::retrieveChunk(  int     nSegmentId,  size_t  nChunkOffset){  ChunkHeader*    pResult = 0;  SegmentHeader*  pSegmentHeader = retrieveSegment( nSegmentId );  if( pSegmentHeader != 0 )  {    size_t  nOffset = 0;    size_t  nMaxOffset = pSegmentHeader -> m_nSize;    byte*   pBytes = ( byte* ) ( pSegmentHeader + 1 );    while( pResult == 0 && nOffset < nMaxOffset && nOffset <= nChunkOffset )    {      ChunkHeader* pChunkHeader = ( ChunkHeader* ) ( pBytes + nOffset );      if( pChunkHeader -> m_bInUse && nOffset == nChunkOffset )      {        pResult = pChunkHeader;      }      else      {        nOffset += pChunkHeader -> m_nChunkSize;      }    }  }  return pResult;}////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::ChunkHeader* UnixSharedMemory::Object::splitChunk(  ChunkHeader*  pChunkHeader,  size_t        nObjectSize){  ChunkHeader*  pResult = pChunkHeader;  size_t        nChunkSize = pChunkHeader -> m_nChunkSize;  if( nChunkSize > 2 * sizeof( ChunkHeader ) + nObjectSize )  {    byte*   pBytes = ( byte* ) pChunkHeader;    size_t  nRemainingSize = nChunkSize - sizeof( ChunkHeader ) - nObjectSize;    nRemainingSize &= 0xFFFFFFF0;    pResult = ( ChunkHeader* ) ( pBytes + nRemainingSize );    pResult -> m_nChunkSize = nChunkSize - nRemainingSize;    pChunkHeader -> m_nChunkSize = nRemainingSize;  }  return pResult;}////////////////////////////////////////////////////////////////////////////////void UnixSharedMemory::Object::joinChunks(  UnixSharedMemory::Object::SegmentHeader* pSegmentHeader){  size_t  nOffset = 0;  size_t  nMaxOffset = pSegmentHeader -> m_nSize - sizeof( SegmentHeader );  byte*   pBytes = ( byte* ) ( pSegmentHeader + 1 );  while( nOffset < nMaxOffset )  {    ChunkHeader* pChunkHeader = ( ChunkHeader* ) ( pBytes + nOffset );    nOffset += pChunkHeader -> m_nChunkSize;    if( !pChunkHeader -> m_bInUse )    {      ChunkHeader* pTempChunkHeader = ( ChunkHeader* ) ( pBytes + nOffset );      while( nOffset < nMaxOffset && !pTempChunkHeader -> m_bInUse )      {        pChunkHeader -> m_nChunkSize += pTempChunkHeader -> m_nChunkSize;        nOffset += pTempChunkHeader -> m_nChunkSize;        pTempChunkHeader = ( ChunkHeader* ) ( pBytes + nOffset );      }    }  }}////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::SegmentHeader* UnixSharedMemory::Object::createSegment(  size_t          nSegmentKey,  SegmentHeader*  pPreviousSegmentHeader,  size_t          nSegmentSize,  int&            rnSegmentId){  SegmentHeader* pResult;  if( nSegmentSize < 64 * 1024 )  {    nSegmentSize = 64 * 1024;  }  pResult = allocateSegment( nSegmentKey, nSegmentSize, rnSegmentId );  if( pResult != 0 && pPreviousSegmentHeader != 0 )  {    pPreviousSegmentHeader -> m_nNextSegment = rnSegmentId;  }  return pResult;}////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::SegmentHeader* UnixSharedMemory::Object::allocateSegment(  size_t  nSegmentKey,  size_t  nSegmentSize,  int&    rnSegmentId){  SegmentHeader* pResult = 0;  rnSegmentId = shmget( nSegmentKey, sizeof( SegmentHeader ) + nSegmentSize, IPC_CREAT | IPC_EXCL | 0600 );  if( rnSegmentId != -1 )  {    void* pSegmentHeaderVoid = shmat( rnSegmentId, 0, 0 );    if( ( size_t ) pSegmentHeaderVoid != 0xFFFFFFFF )    {      ChunkHeader* pChunkHeader;      pResult = ( SegmentHeader* ) pSegmentHeaderVoid;      pResult -> m_nMagic = 0x22021969;      pResult -> m_nSize = sizeof( SegmentHeader ) + nSegmentSize;      pResult -> m_nNextSegment = 0;      pChunkHeader = ( ChunkHeader* ) ( pResult + 1 );      pChunkHeader -> m_bInUse = false;      pChunkHeader -> m_nChunkSize = nSegmentSize;      pChunkHeader -> m_nObjectSize = 0;    }  }  return pResult;}////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::SegmentHeader* UnixSharedMemory::Object::retrieveSegment(  size_t  nSegmentKey,  int&    rnSegmentId){  SegmentHeader* pResult = 0;  rnSegmentId = shmget( nSegmentKey, 0, 0600 );  if( rnSegmentId != -1 )  {    pResult = retrieveSegment( rnSegmentId );  }  return pResult;}////////////////////////////////////////////////////////////////////////////////UnixSharedMemory::Object::SegmentHeader* UnixSharedMemory::Object::retrieveSegment(  int nSegmentId){  SegmentHeader*  pResult = 0;  void*           pSegmentHeaderVoid = shmat( nSegmentId, 0, 0 );  if( ( size_t ) pSegmentHeaderVoid != 0xFFFFFFFF )  {    pResult = ( SegmentHeader* ) pSegmentHeaderVoid;    if( pResult -> m_nMagic != 0x22021969 )    {      shmdt( pSegmentHeaderVoid );      pResult = 0;    }  }  return pResult;}////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -