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.
11 * @author Chris Cleeland <cleeland@ociweb.com>
13 //=============================================================================
16 #include "test_config.h"
20 #if defined (ACE_HAS_THREADS)
21 #include "ace/Lock_Adapter_T.h"
22 #include "ace/OS_NS_stdio.h"
23 #include "ace/OS_NS_string.h"
24 #include "ace/OS_NS_unistd.h"
26 // Number of iterations to run the test.
27 #if defined (ACE_VXWORKS)
28 const unsigned long MAX_THREAD
= 500;
30 # ifdef ACE_FACE_SAFETY_BASE
31 const unsigned long MAX_THREAD
= 10000;
33 const unsigned long MAX_THREAD
= 100000;
39 // Change this to 'true' if you want lots of debugging messages in the log
40 const bool PRINT_DEBUG_MSGS
= true;
46 * @brief Defines a thread pool abstraction based on the <ACE_Task>.
48 class Thread_Pool
: public ACE_Task
<ACE_MT_SYNCH
>
51 /// Create the thread pool containing <n_threads>.
52 Thread_Pool (int n_threads
);
55 ~Thread_Pool () override
;
57 /// Iterate <n_iterations> time printing off a message and "waiting"
58 /// for all other threads to complete this iteration.
61 /// Start the threads in the pool.
64 unsigned long total_threads()
66 return this->total_activated_threads_
.value();
69 /// Number of threads to spawn.
72 /// Returns true iff failed_ == false.
76 //FUZZ: disable check_for_lack_ACE_OS
77 /// Spawn the threads in the pool.
78 int open (void * = 0) override
;
81 ///FUZZ: enable check_for_lack_ACE_OS
82 int close (u_long
) override
;
84 /// Total number of threads activated through this thread pool ever.
85 ACE_Atomic_Op
<ACE_Thread_Mutex
, unsigned long> total_activated_threads_
;
87 /// Flag set only in worker threads to indicate whether they should print
91 /// Flag indicating that start() failed.
96 Thread_Pool::operator!()
98 return ! this->failed_
;
101 Thread_Pool::~Thread_Pool ()
106 Thread_Pool::close (u_long
)
109 ACE_DEBUG ((LM_DEBUG
,
110 ACE_TEXT ("(%P|%t) worker thread closing down\n")));
114 Thread_Pool::Thread_Pool (int n_threads
)
115 : n_threads_ (n_threads
)
116 , total_activated_threads_ (0)
123 Thread_Pool::start ()
125 this->failed_
= false;
126 if (this->open () == -1)
128 ACE_DEBUG ((LM_DEBUG
,
129 ACE_TEXT ("(%P|%t) thread activation ")
130 ACE_TEXT ("failed after %u threads\n"),
131 this->total_threads()));
132 this->failed_
= true;
139 unsigned long t
= ++this->total_activated_threads_
;
140 if (PRINT_DEBUG_MSGS
) // change this to 'true' for debugging
141 this->doprint_
= (t
> 65530);
144 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT(" (%P|%t) thread started.\n")));
146 // Note that the <ACE_Task::svc_run> method automatically removes us
147 // from the <ACE_Thread_Manager> when the thread exits.
156 Thread_Pool::open (void *)
158 if (PRINT_DEBUG_MSGS
)
159 ACE_DEBUG ((LM_DEBUG
,
160 ACE_TEXT ("(%P|%t) pool start %d threads...\n"),
163 if (this->total_activated_threads_
>= (65534 - this->n_threads_
))
166 // Create a pool of worker threads.
167 if (this->activate (THR_NEW_LWP
,
168 this->n_threads_
) == -1)
169 ACE_ERROR_RETURN ((LM_ERROR
,
171 ACE_TEXT ("activate failed")),
177 #endif /* ACE_HAS_THREADS */
181 run_main (int, ACE_TCHAR
*[])
183 ACE_START_TEST (ACE_TEXT ("Thread_Creation_Threshold_Test"));
185 #if defined (ACE_HAS_THREADS)
186 ACE_DEBUG ((LM_DEBUG
,
187 ACE_TEXT ("(%P|%t) will try to start and kill up")
188 ACE_TEXT (" to %u threads sequentially\n"),
190 int initial_pool_size
= 50;
192 // Create the worker tasks.
193 Thread_Pool
thread_pool (initial_pool_size
);
195 while (!thread_pool
&& thread_pool
.total_threads() < MAX_THREAD
)
197 // Activate the task's thread pool, produce the messages that are,
198 // produce the messages that are consumed by the threads in the
199 // thread pool, and demonstrate how to shutdown by enqueueing
200 // "empty" messages into the queue.
201 thread_pool
.start ();
203 // Wait for all the threads to reach their exit point, at which
204 // point the barrier in the destructor of the <ACE_Task> portion of
205 // <Thread_Pool> will return.
206 if (thread_pool
.wait () == -1)
208 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("wait")), 1);
211 if (PRINT_DEBUG_MSGS
)
212 ACE_DEBUG ((LM_DEBUG
,
213 ACE_TEXT ("%u total threads\n"),
214 thread_pool
.total_threads()));
216 int& n_threads
= thread_pool
.n_threads_
;
217 const unsigned long THREAD_THRESHOLD
= 63336;
218 if (thread_pool
.total_threads() >= (THREAD_THRESHOLD
- n_threads
))
222 ACE_DEBUG ((LM_DEBUG
,
223 ACE_TEXT ("%u total threads successfully started and died;")
224 ACE_TEXT (" expected %u.\n"),
225 thread_pool
.total_threads (),
229 ACE_TEXT ("threads not supported on this platform\n")));
230 #endif /* ACE_HAS_THREADS */