/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : SharedData.h                                                  */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#ifndef _SHAREDDATA_H
#define _SHAREDDATA_H

#include <string.h>
#include "semaphore.h"
#include "ourTypes.h"
#include "Exception.h"

/*
CLASS 
SharedData

DESCRIPTION
SharedData is the base class for objects which provide an 
object-oriented interface to shared memory-based IPC.

AUTHOR
Tom O'Reilly
*/
class SharedData {

public:

  ///////////////////////////////////////////////////////////////////
  // AccessError is thrown when read or write is attempted without
  // appropriate Access permission.
  class AccessError : public Exception {
  public:
    AccessError(char *errorMsg) : Exception(errorMsg) {
    }
  };

  ///////////////////////////////////////////////////////////////////
  // Data access types
  enum Access {
    NoAccess, Read, Write, ReadWrite
  };

  ///////////////////////////////////////////////////////////////////
  // Constructor
  SharedData(const char *name, 
	     int nDataBytes,
	     Access access = NoAccess,
	     Boolean init = False);


  ///////////////////////////////////////////////////////////////////
  // Destructor
  virtual ~SharedData();


  ///////////////////////////////////////////////////////////////////
  // Return object name
  const char *name() {
    return _name;
  }


  ///////////////////////////////////////////////////////////////////
  // Set accessibility to shared data
  void setAccess(Access access);


  ///////////////////////////////////////////////////////////////////
  // Return size of data map in bytes
  int mapSize() {
    return _mapSize;
  }


protected:

  ///////////////////////////////////////////////////////////////////
  // Read from shared memory
  // [output] data: mapSize() bytes are copied here
  virtual void read(void *data) 
       throw (AccessError);

  ///////////////////////////////////////////////////////////////////
  // Write to shared memory
  // [input] data: mapSize() bytes are copied from here
  virtual void write(void *data) 
       throw (AccessError);

  ///////////////////////////////////////////////////////////////////
  // Protection flags used by mmap() for specified SharedData::Access
  static int mmapProtectFlags(Access access);

private:

  ///////////////////////////////////////////////////////////////////
  // Release all resources
  void cleanup();

  ///////////////////////////////////////////////////////////////////
  // Initialize shared semaphore
  void initSemaphore();

  ///////////////////////////////////////////////////////////////////
  // Map the shared data memory with specified name (used for semaphore
  // and data maps)
  void map(const char *mapName, void **mapAddr, int mapSize, 
	   Access access);

  // Object name
  const char *_name;
  const char *_protectSemName;
  const char *_notifySemName;

  // Access permission
  Access _access;

  // Pointer to "data protection" semaphore
  sem_t *_protectSem;

  // Pointer to "update notification" semaphore
  sem_t *_notifySem;

  // Size of data (bytes)
  int _mapSize;

  // Pointer to shared memory data segment
  void *_mapAddr;
};


#endif

