Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / examples / Threads / thread_specific.cpp
blob62ff802ca2aa1c0a12962f88709ff0b937ee925a
1 #include "ace/OS_NS_stdio.h"
2 #include "ace/OS_NS_unistd.h"
3 #include "ace/OS_main.h"
4 #include "ace/Service_Config.h"
5 #include "ace/Thread_Manager.h"
6 #include "ace/Signal.h"
7 #include "ace/Truncate.h"
8 #include "ace/Log_Msg.h"
10 #if defined (ACE_HAS_THREADS)
12 #include "thread_specific.h"
14 // Static variables.
15 ACE_MT (ACE_Thread_Mutex Errno::lock_);
16 int Errno::flags_;
18 // This is our thread-specific error handler...
19 static ACE_TSS<Errno> tss_error;
21 // Serializes output via cout.
22 static ACE_SYNCH_MUTEX printf_lock;
24 extern "C" void
25 cleanup (void *ptr)
27 ACE_DEBUG ((LM_DEBUG,
28 "(%t) in cleanup, ptr = %x\n",
29 ptr));
31 delete reinterpret_cast<char *> (ptr);
34 // This worker function is the entry point for each thread.
36 static void *
37 worker (void *c)
39 intptr_t count = reinterpret_cast<intptr_t> (c);
41 ACE_thread_key_t key = ACE_OS::NULL_key;
42 int *ip = 0;
44 // Make one key that will be available when the thread exits so that
45 // we'll have something to cleanup!
47 if (ACE_Thread::keycreate (&key, cleanup) == -1)
48 ACE_ERROR ((LM_ERROR,
49 "(%t) %p\n",
50 "ACE_Thread::keycreate"));
52 ACE_NEW_RETURN (ip,
53 int,
54 0);
56 if (ACE_Thread::setspecific (key, (void *) ip) == -1)
57 ACE_ERROR ((LM_ERROR,
58 "(%t) %p\n",
59 "ACE_Thread::setspecific"));
61 for (intptr_t i = 0; i < count; i++)
63 if (ACE_Thread::keycreate (&key, cleanup) == -1)
64 ACE_ERROR ((LM_ERROR,
65 "(%t) %p\n",
66 "ACE_Thread::keycreate"));
68 ACE_NEW_RETURN (ip,
69 int,
70 0);
72 ACE_DEBUG ((LM_DEBUG,
73 "(%t) in worker 1, key = %d, ip = %x\n",
74 key,
75 ip));
78 // tmp is workaround for gcc strict aliasing warning.
79 void *tmp = reinterpret_cast <void *> (ip);
81 if (ACE_Thread::setspecific (key, tmp) == -1)
82 ACE_ERROR ((LM_ERROR,
83 "(%t) %p\n",
84 "ACE_Thread::setspecific"));
86 if (ACE_Thread::getspecific (key, &tmp) == -1)
87 ACE_ERROR ((LM_ERROR,
88 "(%t) %p\n",
89 "ACE_Thread::setspecific"));
91 if (ACE_Thread::setspecific (key, (void *) 0) == -1)
92 ACE_ERROR ((LM_ERROR,
93 "(%t) %p\n",
94 "ACE_Thread::setspecific"));
97 delete ip;
99 if (ACE_Thread::keyfree (key) == -1)
100 ACE_ERROR ((LM_ERROR,
101 "(%t) %p\n",
102 "ACE_Thread::keyfree"));
104 // Cause an error.
105 ACE_OS::read (ACE_INVALID_HANDLE, 0, 0);
107 // The following two lines set the thread-specific state.
108 tss_error->error (errno);
109 tss_error->line (__LINE__);
111 // This sets the static state (note how C++ makes it easy to do
112 // both).
113 tss_error->flags (ACE_Utils::truncate_cast<int> (count));
116 // Use the guard to serialize access to printf...
117 ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, printf_lock, 0);
119 // Print the thread id portably.
120 ACE_DEBUG ((LM_DEBUG,
121 "(%t) errno = %d, lineno = %d, flags = %d\n",
122 tss_error->error (),
123 tss_error->line (),
124 tss_error->flags ()));
126 key = ACE_OS::NULL_key;
128 if (ACE_Thread::keycreate (&key, cleanup) == -1)
129 ACE_ERROR ((LM_ERROR,
130 "(%t) %p\n",
131 "ACE_Thread::keycreate"));
133 ACE_NEW_RETURN (ip,
134 int,
137 ACE_DEBUG ((LM_DEBUG,
138 "(%t) in worker 2, key = %d, ip = %x\n",
139 key,
140 ip));
143 // Tmp is workaround for GCC strict aliasing warning.
144 void *tmp (reinterpret_cast <void *> (ip));
146 if (ACE_Thread::setspecific (key, tmp) == -1)
147 ACE_ERROR ((LM_ERROR,
148 "(%t) %p\n",
149 "ACE_Thread::setspecific"));
151 if (ACE_Thread::getspecific (key, &tmp) == -1)
152 ACE_ERROR ((LM_ERROR,
153 "(%t) %p\n",
154 "ACE_Thread::setspecific"));
156 if (ACE_Thread::setspecific (key, (void *) 0) == -1)
157 ACE_ERROR ((LM_ERROR,
158 "(%t) %p\n",
159 "ACE_Thread::setspecific"));
162 delete ip;
164 if (ACE_Thread::keyfree (key) == -1)
165 ACE_ERROR ((LM_ERROR,
166 "(%t) %p\n",
167 "ACE_Thread::keyfree"));
170 ACE_DEBUG ((LM_DEBUG,
171 "(%t) exiting\n"));
172 return 0;
175 extern "C" void
176 handler (int signum)
178 ACE_DEBUG ((LM_DEBUG,
179 "signal = %S\n", signum));
180 ACE_Thread_Manager::instance ()->exit (0);
184 ACE_TMAIN (int argc, ACE_TCHAR *argv[])
186 // The Service_Config must be the first object defined in main...
187 ACE_Service_Config daemon (argv[0]);
189 int threads = argc > 1 ? ACE_OS::atoi (argv[1]) : 4;
190 intptr_t count = argc > 2 ? ACE_OS::atoi (argv[2]) : 10000;
192 // Register a signal handler.
193 ACE_Sig_Action sa ((ACE_SignalHandler) (handler), SIGINT);
194 ACE_UNUSED_ARG (sa);
196 #if defined (ACE_HAS_THREADS)
197 if (ACE_Thread_Manager::instance ()->spawn_n (threads,
198 ACE_THR_FUNC (&worker),
199 reinterpret_cast<void *> (count),
200 THR_BOUND | THR_DETACHED) == -1)
201 ACE_ERROR_RETURN ((LM_ERROR,
202 "%p\n",
203 "ACE_Thread_Manager::spawn_n"),
204 -1);
206 ACE_Thread_Manager::instance ()->wait ();
207 #else
208 worker ((void *) count);
209 #endif /* ACE_HAS_THREADS */
210 return 0;
213 #else
215 ACE_TMAIN (int, ACE_TCHAR *[])
217 ACE_ERROR_RETURN ((LM_ERROR,
218 "ACE doesn't support support threads on this platform (yet)\n"),
219 -1);
221 #endif /* ACE_HAS_THREADS */