//============================================================================= /** * @file tss2.cpp * * This program tests various features of ACE_Thread and the * thread-specific storage variant of . * * @author Prashant Jain and Doug Schmidt */ //============================================================================= #include "ace/OS_main.h" #include "ace/Thread.h" #include "ace/Log_Msg.h" #include "ace/Atomic_Op.h" #include "TSS_Data.h" #include "TSS_Obj.h" #include "TSS_Task.h" #if defined (ACE_HAS_THREADS) const int MAX_TASKS = 4; const int MAX_ITERATIONS = 10; ACE_Atomic_Op Test_Task::count_ (0); ACE_Atomic_Op Test_Task::wait_count_ (0); ACE_Atomic_Op Test_Task::max_count_ (0); int num_tasks = 0; // ACE synchronization object. static ACE_Token token; ACE_Atomic_Op TSS_Obj::count_ = 0; TSS_Obj::TSS_Obj () { TSS_Obj::count_++; ACE_DEBUG ((LM_DEBUG, "(%t) TSS_Obj+: %d\n", TSS_Obj::count_.value ())); } TSS_Obj::~TSS_Obj () { TSS_Obj::count_--; ACE_DEBUG ((LM_DEBUG, "(%t) TSS_Obj-: %d\n", TSS_Obj::count_.value ())); } Test_Task::Test_Task () { Test_Task::count_++; ACE_DEBUG ((LM_DEBUG, "(%t) Test_Task+: %d\n", Test_Task::count_.value ())); } Test_Task::~Test_Task () { Test_Task::count_--; ACE_DEBUG ((LM_DEBUG, "(%t) Test_Task-: %d\n", Test_Task::count_.value ())); Test_Task::wait_count_--; } void * Test_Task::svc (void *arg) { // When the thread exits this thread-specific object will be deleted // automatically. ACE_TSS tss (new TSS_Obj); TSS_DATA::instance ()->data (arg); Test_Task::wait_count_++; Test_Task::max_count_++; ACE_DEBUG ((LM_DEBUG, "(%t) svc: waiting (data = %u)\n", arg)); // Do a bunch of set operations on the TSS data just to make sure // that it's truly in TSS (it it weren't, the assertion would fail). while (Test_Task::max_count_ < num_tasks) { TSS_DATA::instance ()->data (arg); ACE_Thread::yield (); } ACE_DEBUG ((LM_DEBUG, "(%t) svc: waiting finished (data = %u)\n", arg)); #if 0 ACE_ASSERT (TSS_DATA::instance ()->data () == arg); #endif delete (Test_Task *) arg; return 0; } int Test_Task::open (void *arg) { if (ACE_Thread::spawn ((ACE_THR_FUNC) Test_Task::svc, arg) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Thread::spawn"), 0); return 0; } int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { num_tasks = argc > 1 ? ACE_OS::atoi (argv[1]) : MAX_TASKS; Test_Task **task_arr = 0; ACE_NEW_RETURN (task_arr, Test_Task *[num_tasks], -1); for (int i = 0; i < MAX_ITERATIONS; i++) { ACE_DEBUG ((LM_DEBUG, "(%t) ********* iteration %d **********\n" "Test_Task::max_count_ %d\n", i, Test_Task::max_count_.value ())); Test_Task::max_count_ = 0; for (int j = 0; j < num_tasks; j++) { ACE_NEW_RETURN (task_arr[j], Test_Task, -1); task_arr[j]->open (task_arr[j]); } ACE_DEBUG ((LM_DEBUG, "(%t) waiting for first thread started\n")); for (;;) { ACE_Thread::yield (); if (Test_Task::max_count_ != 0 ) break; } ACE_DEBUG ((LM_DEBUG, "(%t) First thread started\n" "Waiting for all threads finished\n")); for (;;) { if (!(Test_Task::max_count_ == num_tasks && Test_Task::wait_count_ == 0)) { ACE_Thread::yield (); continue; } ACE_DEBUG ((LM_DEBUG, "(%t) Test_Task::max_count_ = %d," " Test_Task::wait_count_ = %d", Test_Task::max_count_.value (), Test_Task::wait_count_.value ())); break; } ACE_DEBUG ((LM_DEBUG, "(%t) all threads finished\n")); } return 0; } ACE_SINGLETON_TEMPLATE_INSTANTIATE(ACE_TSS_Singleton, TSS_Data, ACE_SYNCH_MUTEX); #else int ACE_TMAIN (int, ACE_TCHAR *[]) { ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n")); return 0; } #endif /* ACE_HAS_THREADS */