//============================================================================= /** * @file Recursive_Condition_Bug_Test.cpp * * This test program validates the functionality of the * ACE_Condition template * specialization when combined with the * ACE_Thread_Timer_Queue_Adapter on Win32 and Posix pthreads. * It was added to test for bugs with the ACE_OS recursive * condition implementation. * * @author Leonid Kvetnyi and Douglas C. Schmidt */ //============================================================================= #include "test_config.h" #include "ace/OS_NS_sys_time.h" #include "ace/Task_T.h" #include "ace/Activation_Queue.h" #include "ace/Timer_Heap.h" #include "ace/Timer_Queue_Adapters.h" #include "ace/Condition_Recursive_Thread_Mutex.h" #if defined (ACE_HAS_THREADS) // Number of iterations for the performance tests. static int max_iterations = 30; using Thread_Timer_Queue = ACE_Thread_Timer_Queue_Adapter; class Test_Handler; class Test_Task : public ACE_Task { public: int svc () override { while (--max_iterations > 0) { // dequeue the next object ACE_Message_Block * mb = 0; if (this->getq (mb) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("getq failed")), -1); Test_Handler *handler = reinterpret_cast (mb->base ()); mb->release (); ACE_Time_Value timeout = ACE_OS::gettimeofday () + ACE_Time_Value (1, 0); if (timer_queue_.schedule (reinterpret_cast (handler), this, timeout) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("schedule failed")), -1); ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%t) %d iteration(s) remain\n"), max_iterations)); } timer_queue_.deactivate (); ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%t) leaving the Test_task\n"))); return 0; } //FUZZ: disable check_for_lack_ACE_OS int open (void * = 0) override { //FUZZ: enable check_for_lack_ACE_OS if (ACE_Task::activate (THR_NEW_LWP, 1) != 0) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("Test_Task::activate")), -1); if (0 != timer_queue_.activate ()) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("Test_Task::queue activate")), -1); return 0; } private: Thread_Timer_Queue timer_queue_; }; class Test_Handler : public ACE_Event_Handler { public: int handle_timeout (const ACE_Time_Value &, const void *arg) override { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Test_Handler::handle_timeout\n"))); void *nc_arg = const_cast (arg); Test_Task *test_task = reinterpret_cast (nc_arg); ACE_Message_Block *mb = 0; ACE_NEW_MALLOC_RETURN (mb, static_cast (ACE_Allocator::instance()->malloc (sizeof (ACE_Message_Block))), ACE_Message_Block (sizeof (*this), // size ACE_Message_Block::MB_DATA, // type 0, // cont (char *) this, // data 0, 0, ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY, ACE_Time_Value::zero, ACE_Time_Value::max_time, 0, ACE_Allocator::instance()), // data -1); test_task->putq (mb); return 0; } }; #endif /* ACE_HAS_THREADS */ int run_main (int, ACE_TCHAR *[]) { ACE_START_TEST (ACE_TEXT ("Recursive_Condition_Bug_Test")); #if defined (ACE_HAS_THREADS) // Timer queue usage. Test_Handler handler; Test_Task task; if (0 != task.open ()) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("open")), -1); ACE_Message_Block *mb = 0; ACE_NEW_MALLOC_RETURN (mb, static_cast (ACE_Allocator::instance()->malloc (sizeof (ACE_Message_Block))), ACE_Message_Block (sizeof (handler), // size ACE_Message_Block::MB_DATA, // type 0, // cont (char *) &handler, 0, 0, ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY, ACE_Time_Value::zero, ACE_Time_Value::max_time, 0, ACE_Allocator::instance()), // data -1); if (-1 == task.putq (mb)) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("putq")), -1); if (ACE_Thread_Manager::instance ()->wait () == -1) ACE_ERROR_RETURN ((LM_ERROR, "wait on Thread_Manager failed"), -1); #else ACE_ERROR ((LM_ERROR, ACE_TEXT ("ACE doesn't support recursive condition variables on this platform\n"))); #endif /* ACE_HAS_THREADS */ ACE_END_TEST; return 0; }