summaryrefslogtreecommitdiff
path: root/docs/tutorials/021/page02.html
blob: 1310357d60d81a1ee1bc7cd527b19deada9f8600 (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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<!-- $Id$ -->
<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>"

<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>