<!-- 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 < <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<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple>; template class ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block>; template class ACE_Guard<ACE_SV_Semaphore_Simple>; template class ACE_Write_Guard<ACE_SV_Semaphore_Simple>; template class ACE_Read_Guard<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<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple> <font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block> <font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Guard<ACE_SV_Semaphore_Simple> <font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Write_Guard<ACE_SV_Semaphore_Simple> <font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Read_Guard<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>