2 //=============================================================================
4 * @file Thread_Creation_Threshold_Test.cpp
6 * This test program stresses how many threads can be
7 * consecutively (not simultaneously) created on a platform.
8 * Rather than testing exhaustively, it establishes a
9 * semi-arbitrary upper limit (MAX_THREAD)of threads. The limit
10 * is only partly arbitrary because it was chosen as a value that
11 * exceeded an observed upper limit on the values that Solaris 9
12 * will accept as arguments to thr_concurrency(), used by
13 * ACE_OS::thr_create(THR_NEW_LWP).
15 * @author Chris Cleeland <cleeland@ociweb.com>
17 //=============================================================================
20 #include "test_config.h"
25 #if defined (ACE_HAS_THREADS)
26 #include "ace/Lock_Adapter_T.h"
27 #include "ace/OS_NS_stdio.h"
28 #include "ace/OS_NS_string.h"
29 #include "ace/OS_NS_unistd.h"
31 // Number of iterations to run the test.
32 #if defined (ACE_VXWORKS)
33 const unsigned long MAX_THREAD
= 500;
35 # ifdef ACE_FACE_SAFETY_BASE
36 const unsigned long MAX_THREAD
= 10000;
38 const unsigned long MAX_THREAD
= 100000;
44 // Change this to 'true' if you want lots of debugging messages in the log
45 const bool PRINT_DEBUG_MSGS
= true;
51 * @brief Defines a thread pool abstraction based on the <ACE_Task>.
53 class Thread_Pool
: public ACE_Task
<ACE_MT_SYNCH
>
56 /// Create the thread pool containing <n_threads>.
57 Thread_Pool (int n_threads
);
62 /// Iterate <n_iterations> time printing off a message and "waiting"
63 /// for all other threads to complete this iteration.
64 virtual int svc (void);
66 /// Start the threads in the pool.
69 unsigned long total_threads()
71 return this->total_activated_threads_
.value();
74 /// Number of threads to spawn.
77 /// Returns true iff failed_ == false.
81 //FUZZ: disable check_for_lack_ACE_OS
82 /// Spawn the threads in the pool.
83 virtual int open (void * = 0);
86 ///FUZZ: enable check_for_lack_ACE_OS
87 virtual int close (u_long
);
89 /// Total number of threads activated through this thread pool ever.
90 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> total_activated_threads_
;
92 /// Flag set only in worker threads to indicate whether they should print
96 /// Flag indicating that start() failed.
101 Thread_Pool::operator!()
103 return ! this->failed_
;
106 Thread_Pool::~Thread_Pool (void)
111 Thread_Pool::close (u_long
)
114 ACE_DEBUG ((LM_DEBUG
,
115 ACE_TEXT ("(%P|%t) worker thread closing down\n")));
119 Thread_Pool::Thread_Pool (int n_threads
)
120 : n_threads_ (n_threads
)
121 , total_activated_threads_ (0)
128 Thread_Pool::start ()
130 this->failed_
= false;
131 if (this->open () == -1)
133 ACE_DEBUG ((LM_DEBUG
,
134 ACE_TEXT ("(%P|%t) thread activation ")
135 ACE_TEXT ("failed after %u threads\n"),
136 this->total_threads()));
137 this->failed_
= true;
142 Thread_Pool::svc (void)
144 unsigned long t
= ++this->total_activated_threads_
;
145 if (PRINT_DEBUG_MSGS
) // change this to 'true' for debugging
146 this->doprint_
= (t
> 65530);
149 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT(" (%P|%t) thread started.\n")));
151 // Note that the <ACE_Task::svc_run> method automatically removes us
152 // from the <ACE_Thread_Manager> when the thread exits.
161 Thread_Pool::open (void *)
163 if (PRINT_DEBUG_MSGS
)
164 ACE_DEBUG ((LM_DEBUG
,
165 ACE_TEXT ("(%P|%t) pool start %d threads...\n"),
168 if (this->total_activated_threads_
>= (65534 - this->n_threads_
))
171 // Create a pool of worker threads.
172 if (this->activate (THR_NEW_LWP
,
173 this->n_threads_
) == -1)
174 ACE_ERROR_RETURN ((LM_ERROR
,
176 ACE_TEXT ("activate failed")),
182 #endif /* ACE_HAS_THREADS */
186 run_main (int, ACE_TCHAR
*[])
188 ACE_START_TEST (ACE_TEXT ("Thread_Creation_Threshold_Test"));
190 #if defined (ACE_HAS_THREADS)
191 ACE_DEBUG ((LM_DEBUG
,
192 ACE_TEXT ("(%P|%t) will try to start and kill up")
193 ACE_TEXT (" to %u threads sequentially\n"),
195 int initial_pool_size
= 50;
197 // Create the worker tasks.
198 Thread_Pool
thread_pool (initial_pool_size
);
200 while (!thread_pool
&& thread_pool
.total_threads() < MAX_THREAD
)
202 // Activate the task's thread pool, produce the messages that are,
203 // produce the messages that are consumed by the threads in the
204 // thread pool, and demonstrate how to shutdown by enqueueing
205 // "empty" messages into the queue.
206 thread_pool
.start ();
208 // Wait for all the threads to reach their exit point, at which
209 // point the barrier in the destructor of the <ACE_Task> portion of
210 // <Thread_Pool> will return.
211 if (thread_pool
.wait () == -1)
213 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("wait")), 1);
216 if (PRINT_DEBUG_MSGS
)
217 ACE_DEBUG ((LM_DEBUG
,
218 ACE_TEXT ("%u total threads\n"),
219 thread_pool
.total_threads()));
221 int& n_threads
= thread_pool
.n_threads_
;
222 const unsigned long THREAD_THRESHOLD
= 63336;
223 if (thread_pool
.total_threads() >= (THREAD_THRESHOLD
- n_threads
))
227 ACE_DEBUG ((LM_DEBUG
,
228 ACE_TEXT ("%u total threads successfully started and died;")
229 ACE_TEXT (" expected %u.\n"),
230 thread_pool
.total_threads (),
234 ACE_TEXT ("threads not supported on this platform\n")));
235 #endif /* ACE_HAS_THREADS */