summaryrefslogtreecommitdiff
path: root/tests/MT_Reactor_Timer_Test.cpp
blob: bf32e777b9d155c021384e987150b4c087b95086 (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
// $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 "test_config.h"
#include "MT_Reactor_Timer_Test.h"

#if defined(__BORLANDC__) && __BORLANDC__ >= 0x0530
USELIB("..\ace\aced.lib");
//---------------------------------------------------------------------------
#endif /* defined(__BORLANDC__) && __BORLANDC__ >= 0x0530 */

#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));
  this->my_reactor_.owner (ACE_OS::thr_self ());
  this->my_reactor_.schedule_timer (this, (const void *) 0,
                                    ACE_Time_Value (1),
                                    ACE_Time_Value (1));
  this->my_reactor_.run_event_loop (backstop);
  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,
                  ASYS_TEXT ("%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;

      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 ();
        }
      return 0;
    }

  ACE_DEBUG ((LM_DEBUG,
              ASYS_TEXT ("%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, ASYS_TCHAR *[])
{
  ACE_START_TEST (ASYS_TEXT ("MT_Reactor_Timer_Test"));

#if defined (ACE_HAS_THREADS)

  Time_Handler other_thread;

  the_reactor = ACE_Reactor::instance ();

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

  the_reactor->schedule_timer (&other_thread,
                               (const void *) 1,
                               ACE_Time_Value (5));

  other_thread.activate (THR_NEW_LWP | THR_JOINABLE);
  the_reactor->run_event_loop ();
  other_thread.wait ();
#else
  ACE_ERROR ((LM_ERROR, ASYS_TEXT ("threads not supported on this platform\n")));
#endif /* ACE_HAS_THREADS */

  ACE_END_TEST;
  return 0;
}