summaryrefslogtreecommitdiff
path: root/docs/tutorials/021/page02.html
blob: 0c1a4014b61b646017c56ed84762a17cde19a8bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<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>// $Id$</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>"

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 pool.)
        */</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>"));
    }

    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_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_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>
</PRE>
<P><HR WIDTH="100%">
<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER>