Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / ACE / tests / MM_Shared_Memory_Test.cpp
bloba291d1fa3210380c833b7c0be47644607343b599
2 //=============================================================================
3 /**
4 * @file MM_Shared_Memory_Test.cpp
6 * This is a simple test of <ACE_Shared_Memory_MM>. The test
7 * forks two processes or spawns two threads (depending upon the
8 * platform) and then executes child and parent allowing them to
9 * exchange data using shared memory. No user input is required as
10 * far as command line arguments are concerned.
12 * @author Prashant Jain <pjain@cs.wustl.edu> and Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
14 //=============================================================================
16 #include "test_config.h"
17 #include "ace/Shared_Memory_MM.h"
18 #include "ace/SV_Semaphore_Simple.h"
19 #include "ace/Process_Semaphore.h"
20 #include "ace/Thread_Manager.h"
21 #include "ace/Lib_Find.h"
22 #include "ace/OS_NS_string.h"
23 #include "ace/OS_NS_unistd.h"
24 #include "ace/ACE.h"
26 #if !defined (ACE_LACKS_MMAP)
28 static const char ACE_ALPHABET[] = "abcdefghijklmnopqrstuvwxyz";
29 const int SHMSZ = 27;
30 static ACE_TCHAR *shm_key;
32 #if defined (ACE_LACKS_FORK)
33 #include "ace/Thread_Semaphore.h"
34 typedef ACE_Thread_Semaphore SYNCHRONIZER;
35 #define SYNC_EXTRA_ARGS
36 #elif defined (ACE_HAS_POSIX_SEM) && defined(ACE_HAS_SYSV_IPC)
37 /**
38 * @class SYNCHRONIZER
40 * @brief If the platform has native cross-process POSIX semaphores, we
41 * must *force* this test to use the System V Semaphores in order
42 * to get the right semantics.
44 class SYNCHRONIZER : public ACE_SV_Semaphore_Simple
46 public:
47 SYNCHRONIZER (int initial_value)
48 : ACE_SV_Semaphore_Simple ((const char *) 0,
49 ACE_SV_Semaphore_Simple::ACE_CREATE,
50 initial_value)
53 #define SYNC_EXTRA_ARGS
54 #else
56 typedef ACE_Process_Semaphore SYNCHRONIZER;
58 #define SYNC_EXTRA_ARGS , sem_name ()
59 ACE_TCHAR sem_name_[ACE_UNIQUE_NAME_LEN] = ACE_TEXT ("/");
61 const ACE_TCHAR *sem_name ()
63 ACE::unique_name (sem_name_, sem_name_ + 1, ACE_UNIQUE_NAME_LEN - 1);
64 return sem_name_;
66 #endif /* !defined (ACE_LACKS_FORK) */
68 // Synchronize the start of the parent and the child.
69 static SYNCHRONIZER *synchronizer = 0;
71 static void *
72 child (void * = 0)
74 int result;
76 // Wait for the parent to be initialized.
77 result = synchronizer->acquire ();
78 ACE_TEST_ASSERT (result != -1);
80 const char *t = ACE_ALPHABET;
81 ACE_Shared_Memory_MM shm_child;
83 result = shm_child.open (shm_key);
84 ACE_TEST_ASSERT (result != -1);
86 char *shm = (char *) shm_child.malloc ();
88 ACE_TEST_ASSERT (shm != 0);
90 for (char *s = shm; *s != '\0'; s++)
92 ACE_TEST_ASSERT (*t == s[0]);
93 t++;
96 // Indicate to the parent that we're done.
97 *shm = '*';
99 return 0;
102 static void *
103 parent (void * = 0)
105 int result;
106 ACE_Shared_Memory_MM shm_parent;
108 result = shm_parent.open (shm_key, SHMSZ);
109 ACE_TEST_ASSERT (result != -1);
111 char *shm = (char *) shm_parent.malloc ();
113 ACE_TEST_ASSERT (shm != 0);
115 char *s = shm;
117 for (const char *c = ACE_ALPHABET; *c != '\0'; c++)
118 *s++ = *c;
120 *s = '\0';
122 // Allow the child to proceed.
123 result = synchronizer->release ();
124 ACE_TEST_ASSERT (result != -1);
126 // Perform a "busy wait" until the child sets the character to '*'.
127 while (*shm != '*')
128 ACE_DEBUG ((LM_DEBUG,
129 ACE_TEXT ("(%P) spinning in parent!\n")));
131 result = shm_parent.remove ();
132 ACE_TEST_ASSERT (result != -1);
134 ACE_OS::unlink (shm_key);
135 return 0;
138 static int
139 spawn ()
141 // Create the synchronizer before spawning the child process/thread,
142 // to avoid race condition between the creation in the parent and
143 // use in the child.
144 ACE_NEW_RETURN (synchronizer,
145 SYNCHRONIZER (0u /*locked*/ SYNC_EXTRA_ARGS),
146 -1);
148 #if !defined (ACE_LACKS_FORK)
149 switch (ACE_OS::fork (ACE_TEXT ("child")))
151 case -1:
152 ACE_ERROR_RETURN ((LM_ERROR,
153 ACE_TEXT ("(%P|%t) %p\n"),
154 ACE_TEXT ("fork failed")),
156 /* NOTREACHED */
157 case 0:
158 child ();
159 // Remove the semaphore.
160 synchronizer->remove ();
161 delete synchronizer;
162 break;
163 /* NOTREACHED */
164 default:
165 parent ();
166 delete synchronizer;
167 break;
168 /* NOTREACHED */
170 #elif defined (ACE_HAS_THREADS)
171 if (ACE_Thread_Manager::instance ()->spawn
172 (ACE_THR_FUNC (child),
173 (void *) 0,
174 THR_NEW_LWP | THR_DETACHED) == -1)
175 ACE_ERROR_RETURN ((LM_ERROR,
176 ACE_TEXT ("(%P|%t) %p\n"),
177 ACE_TEXT ("thread create failed")),
179 else if (ACE_Thread_Manager::instance ()->spawn
180 (ACE_THR_FUNC (parent),
181 (void *) 0,
182 THR_NEW_LWP | THR_DETACHED) == -1)
183 ACE_ERROR_RETURN ((LM_ERROR,
184 ACE_TEXT ("(%P|%t) %p\n"),
185 ACE_TEXT ("thread create failed")),
187 ACE_Thread_Manager::instance ()->wait ();
188 delete synchronizer;
189 #else
190 ACE_UNUSED_ARG (synchronizer);
191 ACE_ERROR_RETURN ((LM_ERROR,
192 ACE_TEXT ("only one thread may be run in a process on this platform\n")),
194 #endif /* ACE_HAS_THREADS */
195 return 0;
197 #endif /* !ACE_LACKS_MMAP */
200 run_main (int, ACE_TCHAR *[])
202 ACE_START_TEST (ACE_TEXT ("MM_Shared_Memory_Test"));
204 #if !defined (ACE_LACKS_MMAP) && !defined (ACE_DISABLE_MKTEMP)
205 ACE_TCHAR temp_file[MAXPATHLEN + 1];
207 // Get the temporary directory,
208 // The - 24 is for the filename, mm_shared_mem_testXXXXXX
209 if (ACE::get_temp_dir (temp_file, MAXPATHLEN - 24) == -1)
210 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Temporary path too long\n")), -1);
212 // Add the filename to the end
213 ACE_OS::strcat (temp_file, ACE_TEXT ("mm_shared_mem_testXXXXXX"));
215 // Store in the global variable.
216 shm_key = temp_file;
218 if (ACE_OS::mktemp (shm_key) == 0
219 || (ACE_OS::unlink (shm_key) == -1
220 && errno == EPERM))
221 ACE_ERROR_RETURN ((LM_ERROR,
222 ACE_TEXT ("(%P|%t) %p\n"),
223 shm_key),
225 spawn ();
227 #else /* !ACE_LACKS_MMAP */
228 ACE_ERROR ((LM_INFO,
229 ACE_TEXT ("mmap and mktemp")
230 ACE_TEXT ("are required for this test\n")));
231 #endif /* !ACE_LACKS_MMAP */
233 ACE_END_TEST;
234 return 0;