summaryrefslogtreecommitdiff
path: root/TAO/examples/AMH/Sink_Server/AMH_Servant.cpp
blob: fa1ef36c47780a30935f7fd2b35d6b00bee3ba0e (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
//
// $Id$
//

#include "AMH_Servant.h"
#include "Timer_Handler.h"

#include "ace/Reactor.h"
#include "ace/Get_Opt.h"


AMH_Servant::AMH_Servant (CORBA::ORB_ptr orb)
  : sleep_time_ (0)
{
  // @@ Mayur, why do you obtain the reactor each time this method is
  //    called?  Why not just cache it once in the constructor.
  //    Furthermore, you don't appear to need the ORB pseudo-reference
  //    anything other than to obtain the Reactor.  Why not just
  //    remove the cached ORB pseudo-reference altogether?
  //
  // Mayur: Good point.  Never crossed my mind :)
  this->reactor_ = orb->orb_core ()->reactor ();
}

AMH_Servant::~AMH_Servant (void)
{
}

int
AMH_Servant::parse_args (int &argc, char **argv)
{
  // *** To get correct behaviour, SET POSIXLY_CORECT=1 on Linux
  // systems!!! ***
  ACE_Get_Arg_Opt<char> get_opts (argc, argv, "s:");
  int c;

  int count_argv = 0;
  while ((c = get_opts ()) != -1)
    {
      ++count_argv;
      switch (c)
        {
        case 's':
          {
            int time = ACE_OS::atoi (get_opts.opt_arg ());
            if (time >= 0)
              this->sleep_time_ = time;

            // Remove the option '-s' from argv []
            // to avoid any confusion that might result.
            {
              for (int i = count_argv; i < argc; i++)
                argv [i] = argv [i+2];
            }

            // Decrement the value of this->argc_ to reflect the removal
            // of '-s' option.
            argc = argc - 2;

            return 1;
          }

        case '?':
        default:
          // Don't do anything.
          break;
        }
    }
  return 0;
}

// Note: Only the following three methods will be called in the event
// loop.  If we make sure these three methods are thread safe, the
// entire class is thread-safe.

void
AMH_Servant::test_method (Test::AMH_RoundtripResponseHandler_ptr _tao_rh,
                          Test::Timestamp send_time
                          ACE_ENV_ARG_DECL)
  ACE_THROW_SPEC ((CORBA::SystemException))
{
  ACE_TRY
    {
      // @@ Mayur, the below Timer_Handler instance will leak if your
      //    schedule_timer() call below fails (which you do not check
      //    for).  If the schedule_timer() call fails, then you should
      //    delete() the Timer_Handler instance.
      //
      // Done.

      // Handler will 'kill' itself when it is done.
      Timer_Handler *handler = new Timer_Handler (_tao_rh,
                                                  send_time);

      // We assume the schedule_timer method is thread-safe
      long l = this->reactor_->schedule_timer (handler,
                                               (void *) 0,
                                               ACE_Time_Value (0, this->sleep_time_));
      ACE_TRY_CHECK;

      if (l == -1) //schedule timer failed
        {
          // free memory
          delete handler;

          // send a no-op to the client
          _tao_rh->test_method (static_cast<Test::Timestamp> (0));

          // just in case we add code later on after this if stmt
          return;
        }
    }
  ACE_CATCHANY
    {
      ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Exception in start_test \n");
    }
  ACE_ENDTRY;

  // Footnote: This method is thread-safe:
  // - We have no common state (and don't alter any).
  // - We do things only through function calls which means we are using
  //   the thread-specific stack for that function call.
}

void
AMH_Servant::start_test (Test::AMH_RoundtripResponseHandler_ptr _tao_rh
                         ACE_ENV_ARG_DECL)
  ACE_THROW_SPEC ((CORBA::SystemException))
{
  ACE_TRY
    {
      _tao_rh->start_test ();
      ACE_TRY_CHECK;
    }
  ACE_CATCHANY
    {
      ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Exception in start_test \n");
    }
  ACE_ENDTRY;
}

void
AMH_Servant::end_test (Test::AMH_RoundtripResponseHandler_ptr _tao_rh
                         ACE_ENV_ARG_DECL)
  ACE_THROW_SPEC ((CORBA::SystemException))
{
  ACE_TRY
    {
      _tao_rh->end_test ();
      ACE_TRY_CHECK;
    }
  ACE_CATCHANY
    {
      ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Exception in end_test \n");
    }
  ACE_ENDTRY;
}


//Global Footnote: This whole class seems to be thread-safe (and look ma, no locks! :)