summaryrefslogtreecommitdiff
path: root/tests/CLASSIX/CLASSIX_Select_Reactor_Test.cpp
blob: 8e124ebc54f88bebc4411fbc8a228d96099a8d3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* -*- C++ -*- */
// $Id$

// ============================================================================
//
// = LIBRARY
//    tests
// 
// = FILENAME
//    MT_Reactor_Timer_Test.cpp
//
// = DESCRIPTION
//      This is a simple test that illustrates the timer mechanism of
//      the reactor scheduling timers, handling expired timers and
//      cancelling scheduled timers from multiple threads.
//      No command line arguments are needed to run the test.
//
// = AUTHOR
//    Steve Huston
// 
// ============================================================================

#include "CLASSIX_test_config.h"
#include "CLASSIX_Select_Reactor_Test.h"

#if defined (ACE_HAS_THREADS)

static ACE_Reactor *the_reactor;

Time_Handler::Time_Handler (void)
{
  for (int i = 0;
       i < Time_Handler::TIMER_SLOTS;
       this->timer_id_[i++] = -1)
    continue;
}

// Set up initial timer conditions.

void 
Time_Handler::setup (void)
{
  this->timer_id_[1] = the_reactor->schedule_timer (this,
                                                    (const void *) 1,
                                                    ACE_Time_Value (5));
}


// In the secondary thread, set a heartbeat timer to go off every
// second.  The heartbeat checks the status of things to be sure
// they're being set and expired correctly.

int 
Time_Handler::svc (void)
{
  ACE_Time_Value backstop (30);

  this->timer_id_[2] = the_reactor->schedule_timer(this,
                                                   (const void *) 2,
                                                   ACE_Time_Value (3));
  ACE_thread_t tid;
  this->my_reactor_.owner(&tid);
  ACE_DEBUG((LM_DEBUG, "((%t) hearbeat reactor's owner was %d\n", tid));
  this->my_reactor_.owner (ACE_Thread::self ());
  this->my_reactor_.owner(&tid);
  ACE_DEBUG((LM_DEBUG, "((%t) hearbeat reactor's owner is %d\n", tid));

  long id = this->my_reactor_.schedule_timer (this, (const void *) 0,
                                    ACE_Time_Value (1),
                                    ACE_Time_Value (1));
  this->my_reactor_.owner(&tid);

  while (!ACE_Reactor::event_loop_done())
  {
      int result = this->my_reactor_.handle_events (backstop);
      if (result == -1)
         break;
    }

  ACE_DEBUG((LM_DEBUG, "(%T(%t) exit from heartbeat\n"));
  return 0;
}

int 
Time_Handler::handle_timeout (const ACE_Time_Value &tv,
                              const void *arg)
{
  long time_tag = long (arg);
  ACE_UNUSED_ARG(tv);

  if (time_tag == 0) 
    {	// Heartbeat.
      int i;

      ACE_DEBUG ((LM_DEBUG,
                  "%T (%t): heartbeat\n"));
      // See if all of the timers have fired.  If so, leave the thread's
      // reactor loop which will exit the thread and end the test.

      for (i = 0; i < Time_Handler::TIMER_SLOTS; i++) 
        if (this->timer_id_[i] != -1)
          break;

      ACE_DEBUG ((LM_DEBUG,
                  "%T (%t): heartbeat done: time slot = %d\n", i));
      if (i == Time_Handler::TIMER_SLOTS)
        {	// All timers should be gone.

          // Cancel heartbeat.
          ACE_ASSERT (this->my_reactor_.cancel_timer (this) == 1);	

          // Shouldn't be any.
          ACE_ASSERT (the_reactor->cancel_timer (this) == 0); 
          this->my_reactor_.end_event_loop ();
	  ACE_DEBUG ((LM_DEBUG,
		      "%T (%t): event loop ended\n"));
        }
      return 0;
    }

  ACE_DEBUG ((LM_DEBUG,
              "%T (%t): Timer #%d (id #%d) expired\n",
              time_tag,
              this->timer_id_[time_tag]));

  ACE_ASSERT (this->timer_id_[time_tag] != -1);
  this->timer_id_[time_tag] = -1;

  return 0;
}

#endif /* ACE_HAS_THREADS */


int
main (int, char *[])
{
  ACE_START_TEST ("Select_Reactor_Test");

#if defined (ACE_HAS_THREADS)

  the_reactor = ACE_Reactor::instance ();
  Time_Handler other_thread;


  // Set up initial set of timers.
  other_thread.setup ();

  #if 0
  the_reactor->schedule_timer (&other_thread,
                               (const void *) 1,
                               ACE_Time_Value (5));
  #endif /* 0 */

  other_thread.activate (THR_NEW_LWP | THR_JOINABLE);
  the_reactor->run_event_loop ();
  ACE_DEBUG ((LM_DEBUG,
	      "%T (%t): waiting for thread to exit\n"));
  other_thread.wait ();
#else
  ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
#endif /* ACE_HAS_THREADS */

  ACE_END_TEST;
  return 0;
}