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"
15 ACE_MT (ACE_Thread_Mutex
Errno::lock_
);
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
;
28 "(%t) in cleanup, ptr = %x\n",
31 delete reinterpret_cast<char *> (ptr
);
34 // This worker function is the entry point for each thread.
39 intptr_t count
= reinterpret_cast<intptr_t> (c
);
41 ACE_thread_key_t key
= ACE_OS::NULL_key
;
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)
50 "ACE_Thread::keycreate"));
56 if (ACE_Thread::setspecific (key
, (void *) ip
) == -1)
59 "ACE_Thread::setspecific"));
61 for (intptr_t i
= 0; i
< count
; i
++)
63 if (ACE_Thread::keycreate (&key
, cleanup
) == -1)
66 "ACE_Thread::keycreate"));
73 "(%t) in worker 1, key = %d, ip = %x\n",
78 // tmp is workaround for gcc strict aliasing warning.
79 void *tmp
= reinterpret_cast <void *> (ip
);
81 if (ACE_Thread::setspecific (key
, tmp
) == -1)
84 "ACE_Thread::setspecific"));
86 if (ACE_Thread::getspecific (key
, &tmp
) == -1)
89 "ACE_Thread::setspecific"));
91 if (ACE_Thread::setspecific (key
, (void *) 0) == -1)
94 "ACE_Thread::setspecific"));
99 if (ACE_Thread::keyfree (key
) == -1)
100 ACE_ERROR ((LM_ERROR
,
102 "ACE_Thread::keyfree"));
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
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",
124 tss_error
->flags ()));
126 key
= ACE_OS::NULL_key
;
128 if (ACE_Thread::keycreate (&key
, cleanup
) == -1)
129 ACE_ERROR ((LM_ERROR
,
131 "ACE_Thread::keycreate"));
137 ACE_DEBUG ((LM_DEBUG
,
138 "(%t) in worker 2, key = %d, ip = %x\n",
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
,
149 "ACE_Thread::setspecific"));
151 if (ACE_Thread::getspecific (key
, &tmp
) == -1)
152 ACE_ERROR ((LM_ERROR
,
154 "ACE_Thread::setspecific"));
156 if (ACE_Thread::setspecific (key
, (void *) 0) == -1)
157 ACE_ERROR ((LM_ERROR
,
159 "ACE_Thread::setspecific"));
164 if (ACE_Thread::keyfree (key
) == -1)
165 ACE_ERROR ((LM_ERROR
,
167 "ACE_Thread::keyfree"));
170 ACE_DEBUG ((LM_DEBUG
,
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
);
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
,
203 "ACE_Thread_Manager::spawn_n"),
206 ACE_Thread_Manager::instance ()->wait ();
208 worker ((void *) count
);
209 #endif /* ACE_HAS_THREADS */
215 ACE_TMAIN (int, ACE_TCHAR
*[])
217 ACE_ERROR_RETURN ((LM_ERROR
,
218 "ACE doesn't support support threads on this platform (yet)\n"),
221 #endif /* ACE_HAS_THREADS */