1 #include "ace/OS_NS_stdio.h"
2 #include "ace/OS_NS_unistd.h"
3 #include "ace/Malloc_T.h"
4 #include "ace/PI_Malloc.h"
5 #include "ace/Process_Mutex.h"
6 #include "ace/Process.h"
7 #include "ace/Unbounded_Queue.h"
8 #include "ace/MMAP_Memory_Pool.h"
10 #define BACKING_STORE "queue.dat"
11 #define QUEUE_NAME "queue.db"
13 typedef ACE_Allocator_Adapter
<ACE_Malloc
<ACE_MMAP_MEMORY_POOL
, ACE_Process_Mutex
> > ALLOCATOR
;
15 ACE_Process_Mutex
coordMutex("Coord-Mutex");
17 // Listing 1 code/ch17
19 class Unbounded_Queue
: public ACE_Unbounded_Queue
<T
>
22 typedef ACE_Unbounded_Queue
<T
> BASE
;
24 Unbounded_Queue(ACE_Allocator
* allocator
)
25 : ACE_Unbounded_Queue
<T
> (allocator
)
28 int enqueue_tail (const T
&new_item
, ACE_Allocator
* allocator
)
30 this->allocator_
= allocator
;
31 return BASE::enqueue_tail (new_item
);
34 int dequeue_head (T
&item
, ACE_Allocator
* allocator
)
36 this->allocator_
= allocator
;
37 return BASE::dequeue_head (item
);
40 void delete_nodes (ACE_Allocator
* allocator
)
42 this->allocator_
= allocator
;
50 typedef Unbounded_Queue
<Record
> QUEUE
;
52 QUEUE
* squeue(ALLOCATOR
* shmem_allocator
)
56 // This is the easy case since if we find hash table in the
57 // memory-mapped file we know it's already initialized.
58 if (shmem_allocator
->find (QUEUE_NAME
, queue
) == 0)
59 return (QUEUE
*) queue
;
61 // Create a new map (because we've just created a new
62 // memory-mapped file).
63 size_t queue_size
= sizeof (QUEUE
);
65 queue
= shmem_allocator
->malloc (queue_size
);
67 // If allocation failed ...
71 new (queue
) QUEUE (shmem_allocator
);
73 if (shmem_allocator
->bind (QUEUE_NAME
, queue
) == -1)
75 // Attempt to clean up.
77 ACE_TEXT ("squeue bind\n")));
78 shmem_allocator
->remove();
86 static ALLOCATOR
* g_shmem_allocator
= 0;
88 // Listing 4 code/ch17
89 int processRecord (ALLOCATOR
*shmem_allocator
)
91 ACE_GUARD_RETURN (ACE_Process_Mutex
, ace_mon
, coordMutex
, -1);
93 QUEUE
* queue
= squeue (shmem_allocator
);
96 delete shmem_allocator
;
97 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("%p\n"),
98 ACE_TEXT ("Could not obtain queue")),
102 if (queue
->is_empty ()) // Check for anything to process.
106 if (queue
->dequeue_head (record
, shmem_allocator
) == -1)
108 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("%p\n"),
109 ACE_TEXT ("dequeue_head\n")),
113 ACE_DEBUG ((LM_DEBUG
,
114 ACE_TEXT ("(%P|%t) Processing record|name: %C")
115 ACE_TEXT ("|Record id1:%d|Record id2:%d\n"),
116 record
.name (), record
.id1 (), record
.id2 ()));
117 if (record
.id1 () == -1)
118 queue
->enqueue_tail (record
, shmem_allocator
);
119 return record
.id1 ();
122 // Listing 5 code/ch17
125 int handle_remap (EXCEPTION_POINTERS
*ep
)
127 ACE_DEBUG ((LM_INFO
, ACE_TEXT ("Handle a remap\n")));
129 DWORD ecode
= ep
->ExceptionRecord
->ExceptionCode
;
130 if (ecode
!= EXCEPTION_ACCESS_VIOLATION
)
131 return EXCEPTION_CONTINUE_SEARCH
;
134 (void *) ep
->ExceptionRecord
->ExceptionInformation
[1];
135 if (g_shmem_allocator
->alloc().memory_pool().remap (addr
) == -1)
136 return EXCEPTION_CONTINUE_SEARCH
;
138 // This is 80x86-specific.
139 ep
->ContextRecord
->Edi
= (DWORD
) addr
;
141 ep
->ContextRecord
->IntA0
=
142 ep
->ContextRecord
->IntV0
= (DWORD
) addr
;
143 ep
->ContextRecord
->IntT5
=
144 ep
->ContextRecord
->IntA0
+ 3;
147 return EXCEPTION_CONTINUE_EXECUTION
;
150 int processWin32Record (ALLOCATOR
*shmem_allocator
)
154 return processRecord (shmem_allocator
);
156 ACE_SEH_EXCEPT (handle_remap (GetExceptionInformation ()))
165 int sendRecord (int recordId
, ALLOCATOR
*shmem_allocator
)
167 ACE_GUARD_RETURN (ACE_Process_Mutex
, ace_mon
, coordMutex
, -1);
169 ACE_DEBUG ((LM_DEBUG
,
170 ACE_TEXT ("(%P|%t) Sending record %d\n"),
173 QUEUE
* queue
= squeue (shmem_allocator
);
175 ACE_OS::sprintf (buf
, "%s:%d", "Record", recordId
);
176 Record
newRecord (recordId
, recordId
+1, buf
);
178 int result
= queue
->enqueue_tail (newRecord
, shmem_allocator
);
180 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("%p\n"),
181 ACE_TEXT ("enqueue failed\n")),
186 // Listing 2 code/ch17
187 int handle_parent (ACE_TCHAR
*cmdLine
)
189 ALLOCATOR
*shmem_allocator
= 0;
190 ACE_MMAP_Memory_Pool_Options options
191 (ACE_DEFAULT_BASE_ADDR
,
192 ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED
);
194 // Create the allocator.
195 ACE_NEW_RETURN (shmem_allocator
,
196 ALLOCATOR (BACKING_STORE
,
201 ACE_Process processa
, processb
;
202 ACE_Process_Options poptions
;
203 const ACE_TCHAR
*args
[3];
205 args
[1] = ACE_TEXT ("a");
207 poptions
.command_line (args
);
208 processa
.spawn (poptions
);
209 processb
.spawn (poptions
);
211 // Make sure the child does map a partial pool in memory.
214 for (int i
= 0; i
< 100; i
++)
215 sendRecord (i
, shmem_allocator
);
216 sendRecord (-1, shmem_allocator
);
220 shmem_allocator
->remove ();
225 // Listing 3 code/ch17
228 ALLOCATOR
*shmem_allocator
= 0;
229 ACE_MMAP_Memory_Pool_Options options
230 (ACE_DEFAULT_BASE_ADDR
,
231 ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED
);
232 ACE_NEW_RETURN (shmem_allocator
,
233 ALLOCATOR (BACKING_STORE
,
237 g_shmem_allocator
= shmem_allocator
;
240 while (processWin32Record (shmem_allocator
) != -1)
243 while (processRecord (shmem_allocator
) != -1)
250 int ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
253 handle_parent(argv
[0]);