//============================================================================= /** * @file test_end_event_loop.cpp * * This program tests the event loop mechanism of the * Proactor. To end the event loop, threads that are blocked in * waiting for completions are woken up and the event loop comes * to the end. This is tested in this program. * Threads are doing with/without time_out * values and the main thread calls . * make * ./test_end_event_loop * * @author Alexander Babu Arulanthu */ //============================================================================= #include "ace/OS_NS_unistd.h" #include "ace/Proactor.h" #include "ace/Task.h" #include "ace/WIN32_Proactor.h" #include "ace/POSIX_Proactor.h" #include "ace/OS_main.h" #if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS) // This only works on Win32 platforms and on Unix platforms supporting // POSIX aio calls. /** * @class My_Task: * * @brief Contains thread functions which execute event loops. Each * thread waits for a different signal. */ class My_Task: public ACE_Task { public: // Constructor. My_Task (void) : time_flag_ (0) {} /// Destructor. virtual ~My_Task (void) {} //FUZZ: disable check_for_lack_ACE_OS // If time_flag is zero do the eventloop indefinitely, otherwise do // it for finite amount of time (13secs!!!). int open (void *timed_event_loop) { //FUZZ: enble check_for_lack_ACE_OS // Set the local variable. if (timed_event_loop == 0) this->time_flag_ = 0; else this->time_flag_ = 1; // Spawn the threads. if (this->activate (THR_NEW_LWP, 5) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%N:%l:%p\n", "My_Task:open: failed"), -1); return 0; } // Thread function. int svc (void) { ACE_DEBUG ((LM_DEBUG, "(%P|%t):Starting svc routine\n")); if (this->time_flag_) { ACE_DEBUG ((LM_DEBUG, "(%P|%t):Going to do *timed* \n")); ACE_Time_Value run_time (13); if (ACE_Proactor::instance ()->run_event_loop (run_time) == -1) ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t):%p.\n", " failed"), -1); } else { ACE_DEBUG ((LM_DEBUG, "(%P|%t):Going to do *indefinite* \n")); if (ACE_Proactor::instance ()->run_event_loop () == -1) ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t):%p.\n", " failed"), -1); } return 0; }; private: /// If zero, indefinite event loop, otherwise timed event loop. int time_flag_; }; int ACE_TMAIN (int argc, ACE_TCHAR *argv []) { ACE_UNUSED_ARG (argc); ACE_UNUSED_ARG (argv); ACE_DEBUG ((LM_DEBUG, "(%P | %t):Test starts\n")); // Let us get the singleton proactor created here. This is very // important. This will mask the signal used in the Proactor masked // for the main thread (and all the threads). ACE_Proactor *proactor = ACE_Proactor::instance (); ACE_UNUSED_ARG (proactor); My_Task task1, task2; // Test the indefinite run event loop. if (task1.open (0) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%N:%l:(%P | %t):Failed to the task\n"), 1); // Test the indefinite run event loop. Just pass a non-zero. if (task2.open ((void *)&task2) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%N:%l:(%P | %t):Failed to the task\n"), 1); // Give a gap. ACE_OS::sleep (3); // End the event loop. if (ACE_Proactor::instance ()->end_event_loop () == -1) ACE_ERROR_RETURN ((LM_ERROR, "%N:%l:(%P | %t):Failed to \n"), 1); ACE_Thread_Manager::instance ()->wait (); ACE_DEBUG ((LM_DEBUG, "(%P | %t):Test ends\n")); return 0; } #else /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */ int ACE_TMAIN (int, ACE_TCHAR *[]) { ACE_DEBUG ((LM_DEBUG, "This example cannot work with AIOCB_Proactor.\n")); return 1; } #endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */