summaryrefslogtreecommitdiff
path: root/ACE/tests/Thread_Creation_Threshold_Test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/tests/Thread_Creation_Threshold_Test.cpp')
-rw-r--r--ACE/tests/Thread_Creation_Threshold_Test.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/ACE/tests/Thread_Creation_Threshold_Test.cpp b/ACE/tests/Thread_Creation_Threshold_Test.cpp
new file mode 100644
index 00000000000..f5f62b84e82
--- /dev/null
+++ b/ACE/tests/Thread_Creation_Threshold_Test.cpp
@@ -0,0 +1,239 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// Thread_Creation_Threshold_Test.cpp
+//
+// = DESCRIPTION
+// This test program stresses how many threads can be
+// consecutively (not simultaneously) created on a platform.
+// Rather than testing exhaustively, it establishes a
+// semi-arbitrary upper limit (MAX_THREAD)of threads. The limit
+// is only partly arbitrary because it was chosen as a value that
+// exceeded an observed upper limit on the values that Solaris 9
+// will accept as arguments to thr_concurrency(), used by
+// ACE_OS::thr_create(THR_NEW_LWP).
+//
+// = AUTHOR
+// Chris Cleeland <cleeland@ociweb.com>
+//
+// ============================================================================
+
+#include "test_config.h"
+#include "ace/Task.h"
+
+
+
+#if defined (ACE_HAS_THREADS)
+#include "ace/Lock_Adapter_T.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+// Number of iterations to run the test.
+#if defined (ACE_VXWORKS)
+const int THREADS_PER_POOL = 50;
+const unsigned long MAX_THREAD = 500;
+#else
+const int THREADS_PER_POOL = 1000;
+const unsigned long MAX_THREAD = 100000;
+#endif
+
+namespace
+{
+ // Change this to 'true' if you want lots of debugging messages in the log
+ const bool PRINT_DEBUG_MSGS = true;
+}
+
+class Thread_Pool : public ACE_Task<ACE_MT_SYNCH>
+{
+ // = TITLE
+ // Defines a thread pool abstraction based on the <ACE_Task>.
+public:
+ Thread_Pool (int n_threads);
+ // Create the thread pool containing <n_threads>.
+
+ ~Thread_Pool (void);
+ // Destructor...
+
+ virtual int svc (void);
+ // Iterate <n_iterations> time printing off a message and "waiting"
+ // for all other threads to complete this iteration.
+
+ void start();
+ // Start the threads in the pool.
+
+ unsigned long total_threads()
+ {
+ return this->total_activated_threads_.value();
+ }
+
+ int n_threads_;
+ // Number of threads to spawn.
+
+ bool operator! ();
+ // Returns true iff failed_ == false.
+
+private:
+ //FUZZ: disable check_for_lack_ACE_OS
+ virtual int open (void * = 0);
+ // Spawn the threads in the pool.
+
+ virtual int close (u_long);
+ // Close hook.
+ //FUZZ: enable check_for_lack_ACE_OS
+
+ ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> total_activated_threads_;
+ // Total number of threads activated through this thread pool ever.
+
+ bool doprint_;
+ // Flag set only in worker threads to indicate whether they should print
+ // debug messages.
+
+ bool failed_;
+ // Flag indicating that start() failed.
+};
+
+bool
+Thread_Pool::operator!()
+{
+ return ! this->failed_;
+}
+
+Thread_Pool::~Thread_Pool (void)
+{
+}
+
+int
+Thread_Pool::close (u_long)
+{
+ if (this->doprint_)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) worker thread closing down\n")));
+ return 0;
+}
+
+Thread_Pool::Thread_Pool (int n_threads)
+ : n_threads_ (n_threads)
+ , total_activated_threads_ (0)
+ , doprint_ (false)
+ , failed_ (false)
+{
+}
+
+void
+Thread_Pool::start ()
+{
+ this->failed_ = false;
+ if (this->open () == -1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) thread activation ")
+ ACE_TEXT ("failed after %u threads\n"),
+ this->total_threads()));
+ this->failed_ = true;
+ }
+}
+
+int
+Thread_Pool::svc (void)
+{
+ unsigned long t = ++this->total_activated_threads_;
+ if (PRINT_DEBUG_MSGS) // change this to 'true' for debugging
+ this->doprint_ = (t > 65530);
+
+ if (this->doprint_)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT(" (%P|%t) thread started.\n")));
+
+ // Note that the <ACE_Task::svc_run> method automatically removes us
+ // from the <ACE_Thread_Manager> when the thread exits.
+ return 0;
+}
+
+namespace {
+ void no_op() { }
+}
+
+int
+Thread_Pool::open (void *)
+{
+ if (PRINT_DEBUG_MSGS)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) pool start %d threads...\n"),
+ this->n_threads_));
+
+ if (this->total_activated_threads_ >= (65534 - this->n_threads_))
+ no_op ();
+
+ // Create a pool of worker threads.
+ if (this->activate (THR_NEW_LWP,
+ this->n_threads_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("activate failed")),
+ -1);
+
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
+
+
+int
+run_main (int, ACE_TCHAR *[])
+{
+ ACE_START_TEST (ACE_TEXT ("Thread_Creation_Threshold_Test"));
+
+#if defined (ACE_HAS_THREADS)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) will try to start and kill up")
+ ACE_TEXT (" to %u threads sequentially\n"),
+ MAX_THREAD));
+ int initial_pool_size = 50;
+
+ // Create the worker tasks.
+ Thread_Pool thread_pool (initial_pool_size);
+
+ while (!thread_pool && thread_pool.total_threads() < MAX_THREAD)
+ {
+ // Activate the task's thread pool, produce the messages that are,
+ // produce the messages that are consumed by the threads in the
+ // thread pool, and demonstrate how to shutdown by enqueueing
+ // "empty" messages into the queue.
+ thread_pool.start ();
+
+ // Wait for all the threads to reach their exit point, at which
+ // point the barrier in the destructor of the <ACE_Task> portion of
+ // <Thread_Pool> will return.
+ if (thread_pool.wait () == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("wait")), 1);
+ }
+
+ if (PRINT_DEBUG_MSGS)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%u total threads\n"),
+ thread_pool.total_threads()));
+
+ int& n_threads = thread_pool.n_threads_;
+ const unsigned long THREAD_THRESHOLD = 63336;
+ if (thread_pool.total_threads() >= (THREAD_THRESHOLD - n_threads))
+ n_threads = 1;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%u total threads successfully started and died;")
+ ACE_TEXT (" expected %u.\n"),
+ thread_pool.total_threads (),
+ MAX_THREAD));
+#else
+ ACE_ERROR ((LM_INFO,
+ ACE_TEXT ("threads not supported on this platform\n")));
+#endif /* ACE_HAS_THREADS */
+ ACE_END_TEST;
+ return 0;
+}