Sophie

Sophie

distrib > Mandriva > 10.0-com > i586 > by-pkgid > 21280410b6ea906d791d7a12afae2579 > files > 367

libace5-doc-5.4-2mdk.i586.rpm

<!-- page02.html,v 1.9 2000/03/19 20:09:34 jcej Exp -->
<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
   <META NAME="Author" CONTENT="James CE Johnson">
   <TITLE>ACE Tutorial 021</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">

<CENTER><B><FONT SIZE=+2>ACE Tutorial 021</FONT></B></CENTER>

<CENTER><B><FONT SIZE=+2>Pooling your memories</FONT></B></CENTER>

<P>
<HR WIDTH="100%">
      The key components for creating the memory pool are:
    <ul>
      <li>Create and name the pool
      <li>Allocate a chunk (region) of memory from the pool
      <li>Name the allocated region
    </ul>
    The rest of it is just critical sections and data manipulation.
<hr>
<PRE>

<font color=red>// page02.html,v 1.9 2000/03/19 20:09:34 jcej Exp</font>

<font color=red>/*
  I've hidden the details in an Allocator class declared in mpool.h
  We'll come to that a little later.
*/</font>
<font color=blue>#include</font> "<font color=green>mpool.h</font>"

<font color=blue>#if defined</font>(<font color=purple>ACE_LACKS_SYSV_SHMEM</font>)
int
main (int, char *[])
{
  ACE_ERROR_RETURN ((LM_ERROR,
                     "<font color=green>System V Semaphores not available on this platform.\n</font>"),100);
}
#else <font color=red>// ACE_LACKS_SYSV_SHMEM</font>
int
main (int, char *[])
{
  <font color=red>/*
    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.)
    */</font>
  Allocator allocator (<font color=#008888>Constants::PoolName</font>);

  <font color=red>/*
    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.
    */</font>
  char *shm = (char *) allocator.pool ().malloc (27);

  ACE_ASSERT (shm != 0);

  <font color=red>/// FYI</font>
  ACE_DEBUG ((LM_INFO,
              "<font color=green>Shared memory is at 0x%x\n</font>",
              shm));

  <font color=red>/*
    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.
    */</font>
  if (allocator.pool ().bind(<font color=#008888>Constants::RegionName</font>,shm) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "<font color=green>Cannot bind the name '%s' to the pointer 0x%x\n</font>",
                       <font color=#008888>Constants::RegionName</font>,
                       shm),
                      100);

  <font color=red>/*
    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.
    */</font>

  ACE_SV_Semaphore_Complex mutex;
  ACE_ASSERT (mutex.open (<font color=#008888>Constants::SEM_KEY_1</font>,
                          <font color=#008888>ACE_SV_Semaphore_Complex::ACE_CREATE</font>,
                          0) != -1);

  ACE_SV_Semaphore_Complex synch;
  ACE_ASSERT (synch.open (<font color=#008888>Constants::SEM_KEY_2</font>,
                          <font color=#008888>ACE_SV_Semaphore_Complex::ACE_CREATE</font>,
                          0) != -1);

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

  <font color=red>/*
    The client will be blocking on an acquire() of mutex.  By
    releasing it here, the client can go look at the shared data.
    */</font>
  if (mutex.release () == -1)
    ACE_ERROR ((LM_ERROR,
                "<font color=green>(%P) %p</font>",
                "<font color=green>server mutex.release</font>"));
  <font color=red>/*
    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.
    */</font>
  else if (synch.acquire () == -1)
    ACE_ERROR ((LM_ERROR,
                "<font color=green>(%P) %p</font>",
                "<font color=green>server synch.acquire</font>"));
  <font color=red>/*
    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.
    */</font>
  if (allocator.pool ().remove () == -1)
    ACE_ERROR ((LM_ERROR,
                "<font color=green>(%P) %p\n</font>",
                "<font color=green>server allocator.remove</font>"));
  <font color=red>/*
    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.
    */</font>

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

<font color=red>/*
  This tutorial was created by shamelessly modifying one of the ACE
  examples.  Someone there had already created the necessary explicit
  template instantiations & I don't want them to go to waste...
 */</font>
<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>)
template class ACE_Malloc&lt;ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple>;
template class ACE_Malloc_T&lt;ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block>;
template class ACE_Guard&lt;ACE_SV_Semaphore_Simple>;
template class ACE_Write_Guard&lt;ACE_SV_Semaphore_Simple>;
template class ACE_Read_Guard&lt;ACE_SV_Semaphore_Simple>;
<font color=blue>#elif defined</font> (<font color=purple>ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA</font>)
<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Malloc&lt;ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple>
<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Malloc_T&lt;ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block>
<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Guard&lt;ACE_SV_Semaphore_Simple>
<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Write_Guard&lt;ACE_SV_Semaphore_Simple>
<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Read_Guard&lt;ACE_SV_Semaphore_Simple>
<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font>

<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font>
</PRE>
<P><HR WIDTH="100%">
<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER>