Example #1
0
static int
child (char *shm)
{
  // Both semaphores are initially created with a count of 0, i.e.,
  // they are "locked."
  ACE_SV_Semaphore_Complex mutex (SEM_KEY_1, ACE_SV_Semaphore_Complex::ACE_CREATE, 0);
  ACE_SV_Semaphore_Complex synch (SEM_KEY_2, ACE_SV_Semaphore_Complex::ACE_CREATE, 0);

  // Perform "busy waiting" here until we acquire the semaphore.  This
  // isn't really a good design -- it's just to illustrate that you
  // can do non-blocking acquire() calls with the ACE System V
  // semaphore wrappers.
  while (mutex.tryacquire () == -1)
    if (errno == EAGAIN)
      ACE_DEBUG ((LM_DEBUG, "spinning in child!\n"));
    else
      ACE_ERROR_RETURN ((LM_ERROR, "child mutex.tryacquire"), 1);

  for (char *s = (char *) shm; *s != '\0'; s++)
    ACE_DEBUG ((LM_DEBUG, "%c", *s));

  ACE_DEBUG ((LM_DEBUG, "\n"));

  if (synch.release () == -1)
    ACE_ERROR_RETURN ((LM_ERROR, "child synch.release"), 1);
  return 0;
}
Example #2
0
static int
child (char *shm)
{
  ACE_SV_Semaphore_Complex sem (SEM_KEY, ACE_SV_Semaphore_Complex::ACE_CREATE, 0, 2);

  while (sem.tryacquire (0) == -1)
    if (errno == EAGAIN)
      ACE_DEBUG ((LM_DEBUG, "spinning in client!\n"));
    else
      ACE_ERROR_RETURN ((LM_ERROR, "client mutex.tryacquire(0)"), 1);

  for (char *s = (char *) shm; *s != '\0'; s++)
    ACE_DEBUG ((LM_DEBUG, "%c", *s));

  ACE_DEBUG ((LM_DEBUG, "\n"));

  if (sem.release (1) < 0)
    ACE_ERROR ((LM_ERROR, "client sem.release(1)"));
  return 0;
}
Example #3
0
static int
parent (char *shm)
{
  char *s = shm;

  // Both semaphores are initially created with a count of 0, i.e.,
  // they are "locked."
  ACE_SV_Semaphore_Complex mutex (SEM_KEY_1, ACE_SV_Semaphore_Complex::ACE_CREATE, 0);
  ACE_SV_Semaphore_Complex synch (SEM_KEY_2, ACE_SV_Semaphore_Complex::ACE_CREATE, 0);

  // This is a critical section, which is protected by the mutex
  // semaphore.
  for (char c = 'a'; c <= 'z'; c++)
    *s++ = c;

  *s = '\0';

  if (mutex.release () == -1)
    ACE_ERROR ((LM_ERROR, "%p", "parent mutex.release"));
  else if (synch.acquire () == -1)
    ACE_ERROR ((LM_ERROR, "%p", "parent synch.acquire"));

  if (my_alloc.remove () == -1)
    ACE_ERROR ((LM_ERROR, "%p\n", "my_alloc.remove"));
  if (mutex.remove () == -1)
    ACE_ERROR ((LM_ERROR, "%p\n", "mutex.remove"));
  if (synch.remove () == -1)
    ACE_ERROR ((LM_ERROR, "%p\n", "synch.remove"));
  return 0;
}
Example #4
0
static int
parent (char *shm)
{
  char *s = shm;

  ACE_SV_Semaphore_Complex sem (SEM_KEY, ACE_SV_Semaphore_Complex::ACE_CREATE, 0, 2);

  for (char c = 'a'; c <= 'z'; c++)
    *s++ = c;

  *s = '\0';

  if (sem.release (0) == -1)
    ACE_ERROR ((LM_ERROR, "%p", "parent sem.release(0)"));
  else if (sem.acquire (1) == -1)
    ACE_ERROR ((LM_ERROR, "%p", "parent sem.acquire(1)"));

  if (alloc.remove () == -1)
    ACE_ERROR ((LM_ERROR, "%p\n", "alloc.remove"));
  if (sem.remove () == -1)
    ACE_ERROR ((LM_ERROR, "%p\n", "sem.remove"));
  return 0;
}
static int
child (char *shm)
{
  int result;

  ACE_SV_Semaphore_Complex mutex;

  // This semaphore is initially created with a count of 0, i.e., it
  // is "locked."
  result = mutex.open (SEM_KEY_1,
                       ACE_SV_Semaphore_Complex::ACE_CREATE,
                       0);
  ACE_ASSERT (result != -1);

  ACE_SV_Semaphore_Complex synch;
  // This semaphore is initially created with a count of 0, i.e., it
  // is "locked."
  result = synch.open (SEM_KEY_2,
                       ACE_SV_Semaphore_Complex::ACE_CREATE,
                       0);
  ACE_ASSERT (result != -1);

  // Perform "busy waiting" here until we acquire the semaphore.  This
  // isn't really a good design -- it's just to illustrate that you
  // can do non-blocking acquire() calls with the ACE System V
  // semaphore wrappers.
  while ((result = mutex.tryacquire ()) == -1)
    if (errno == EAGAIN)
      ACE_DEBUG ((LM_DEBUG,
                  ACE_TEXT ("(%P) spinning in child!\n")));
    else
      {
        ACE_ERROR ((LM_ERROR,
                    ACE_TEXT ("(%P) child mutex.tryacquire")));
        ACE_ASSERT (result != -1);
      }

  for (int i = 0; i < SHMSZ; i++)
    ACE_ASSERT (SHMDATA[i] == shm[i]);

  result = synch.release ();
  ACE_ASSERT (result != -1);

  return 0;
}
int
main (int, char *[])
{
  /*
    Construction of an Allocator will create the memory pool and
    provide it with a name.  The Constants class is also
    declared in mpool.h to keep server and client on the same
    page.  The name is used to generate a unique semaphore which
    prevents simultaneous access to the pools housekeeping
    information.  (Note that you still have to provide your own
    synch mechanisms for the data *you* put in the poo.)
    */
  Allocator allocator (Constants::PoolName);

  /*
    The Allocator class provides the pool() member so that you
    have access to the actual memory pool.  A more robust
    implementation would behave more as a bridge class but this
    is good enough for what we're doing here.
    Once you have a reference to the pool, the malloc() method
    can be used to get some bytes.  If successful, shm will
    point to the data.  Otherwise, it will be zero.
    */
  char *shm = (char *) allocator.pool ().malloc (27);

  ACE_ASSERT (shm != 0);

  /// FYI
  ACE_DEBUG ((LM_INFO,
              "Shared memory is at 0x%x\n",
              shm));

  /*
    Something that we can do with a memory pool is map a name to
    a region provided by malloc.  By doing this, we can
    communicate that name to the client as a rendezvous
    location.  Again, a member of Constants is used to keep the
    client and server coordinated.
    */
  if (allocator.pool ().bind(Constants::RegionName,shm) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "Cannot bind the name '%s' to the pointer 0x%x\n",
                       Constants::RegionName,
                       shm),
                      100);

  /*
    One of the best ways to synch between different processes is
    through the use of semaphores.  ACE_SV_Semaphore_Complex
    hides the gory details and lets us use them rather easily.

    Here, we'll create two semaphores:  mutex and synch.  mutex
    will be used to provide mutually exclusive access to the
    shared region for writting/reading.  synch will be used to
    prevent the server from removing the memory pool before the
    client is done with it.

    Both semaphores are created in an initially locked state.
    */

  ACE_SV_Semaphore_Complex mutex;
  ACE_ASSERT (mutex.open (Constants::SEM_KEY_1,
                          ACE_SV_Semaphore_Complex::ACE_CREATE,
                          0) != -1);

  ACE_SV_Semaphore_Complex synch;
  ACE_ASSERT (synch.open (Constants::SEM_KEY_2,
                          ACE_SV_Semaphore_Complex::ACE_CREATE,
                          0) != -1);

  /*
    We know the mutex is locked because we created it that way.
    Take a moment to write some data into the shared region.
    */
  for (int i = 0; i < Constants::SHMSZ; i++)
    shm[i] = Constants::SHMDATA[i];

  /*
    The client will be blocking on an acquire() of mutex.  By
    releasing it here, the client can go look at the shared data.
    */
  if (mutex.release () == -1)
    ACE_ERROR ((LM_ERROR,
                "(%P) %p",
                "server mutex.release"));
  /*
    Even though we created the synch semaphore in a locked
    state, if we attempt to acquire() it, we will block.  Our
    design requires that the client release() synch when it is
    OK for us to remove the shared memory.
    */
  else if (synch.acquire () == -1)
    ACE_ERROR ((LM_ERROR,
                "(%P) %p",
                "server synch.acquire"));
  /*
    This will remove all of the memory pool's resources.  In the
    case where a memory mapped file is used, the physical file
    will also be removed.
    */
  if (allocator.pool ().remove () == -1)
    ACE_ERROR ((LM_ERROR,
                "(%P) %p\n",
                "server allocator.remove"));
  /*
    We now have to cleanup the semaphores we created.  Use the
    ipcs command to see that they did, indeed, go away after the
    server exits.
    */

  if (mutex.remove () == -1)
    ACE_ERROR ((LM_ERROR,
                "(%P) %p\n",
                "server mutex.remove"));
  else if (synch.remove () == -1)
    ACE_ERROR ((LM_ERROR,
                "(%P) %p\n",
                "server synch.remove"));
  return 0;
}