Česky
Kamil Dudka

Share Library (C++)

File detail

Name:DownloadSharedSegment.cpp [Download]
Location: sharelib > src > sharelib
Size:3.8 KB
Last modification:2007-08-27 01:16

Source code

/**
 * @file SharedSegment.cpp
 * @brief Platform-indepent shared segment representation
 * @author Kamil Dudka, xdudka00@gmail.com
 * @date 2007-05-15
 * @ingroup backend
 */
 
#include "SharedSegment.h"
 
#ifdef _LINUX
#  include <sys/types.h>
#  include <sys/stat.h>
#  include <sys/shm.h>
#endif // _LINUX
 
using namespace Share;
 
void SharedSegment::setName (const char *name)
{
  szName_ = new char[strlen (name) + 1];
  strcpy (szName_, name);
}
 
#ifdef _LINUX
namespace
{
  /**
   * This function was copy-pasted from MDSTk
   * and will be documented later.
   */
  //! Creates a unique system identifier from a given string
  unsigned CreateKey(const std::string& sId)
  {
      // String conversion/hash function parameters
      static const unsigned uShift = 6;
      static const unsigned uMask = ~0U << (16U - uShift);
 
      // String to UInt conversion
      unsigned uHash = 0;
      for (int i = 0; i < (int)sId.length(); i++)
      {
          uHash = (uHash & uMask) ^ (uHash << uShift) ^ sId[i];
      }
 
      // Return the hash
      return (uHash & 0xffff);
  }
}
 
SharedSegment::SharedSegment (const char *name, size_t size) throw (ShareException)
{
  setName (name);
 
  // Create the shared memory key (MDSTk)
  key_t key = static_cast<key_t> (CreateKey(name));
 
  id_= shmget (key, size, IPC_CREAT | IPC_EXCL | 0600);
  if (0 >= id_)
    throw ShareException ("Segment: Unable to create new shared segment - shmget() failed");
  attach ();
}
SharedSegment::SharedSegment (const char *name) throw (ShareException)
{
  setName (name);
 
  // Create the shared memory key (MDSTk)
  key_t key = static_cast<key_t> (CreateKey(name));
 
  id_= shmget (key, 0, 0600);
  if (0 >= id_)
    throw ShareException ("Segment: Unable to attach to existing shared segment - shmget() failed");
  attach ();
}
 
SharedSegment::~SharedSegment () throw ()
{
  //std::cout<<"=== Detaching segment with id "<<id_<<" attached at address "<<atAddr_<<"\n";
  if (atAddr_)
    shmdt (atAddr_);
 
  delete[] szName_;
}
 
void SharedSegment::destroy ()
{
  //std::cout<<"Segment::destroy()\n";
  if (id_);
    shmctl (id_, IPC_RMID, 0);
}
 
void SharedSegment::attach ()
{
  atAddr_= shmat (id_, 0, 0);
  if (!atAddr_)
    throw ShareException ("Segment: Unable to attach shared segment - shmat() failded");
  //std::cout<<"=== Attached segment with id "<<id_<<" at address "<<atAddr_<<"\n";
}
 
#endif // _LINUX
 
#ifdef _WIN32
SharedSegment::SharedSegment (const char *name, size_t size) throw (ShareException)
{
  setName (name);
 
  id_ = CreateFileMappingA (
    INVALID_HANDLE_VALUE,
    0,
    PAGE_READWRITE,
    0,
    static_cast<DWORD>(size),
    name
    );
  if (NULL== id_ || INVALID_HANDLE_VALUE== id_)
    throw ShareException ("Segment: Unable to create new shared segment - CreateFileMappingA() failed");
  if (GetLastError() == ERROR_ALREADY_EXISTS) {
    CloseHandle (id_);
    throw ShareException ("Segment: Unable to create new shared segment - given name already exist");
  }
  this-> attach();
}
 
SharedSegment::SharedSegment (const char *name) throw (ShareException)
{
  setName (name);
 
  id_ = OpenFileMappingA (
    FILE_MAP_WRITE,
    false,
    name
    );
  if (NULL== id_ || INVALID_HANDLE_VALUE== id_)
    throw ShareException ("Segment: Unable to attach to existing shared segment - OpenFileMappingA() failed");
  this-> attach();
}
 
SharedSegment::~SharedSegment ()
{
  if (atAddr_)
    UnmapViewOfFile (atAddr_);
  if (id_)
    CloseHandle (id_);
 
  delete[] szName_;
}
void SharedSegment::attach ()
{
  atAddr_= MapViewOfFile (
    id_,
    FILE_MAP_WRITE,
    0,
    0,
    0
    );
  if (!atAddr_) {
    CloseHandle (id_);
    throw ShareException ("Segment: Unable to attach to shared segment - MapViewOfFile() failed");
  }
}
void SharedSegment::destroy ()
{
  //std::cout << "Segment::destroy()\n";
}
#endif // _WIN32