summaryrefslogtreecommitdiff
path: root/TAO/tests/POA/Reference_Counting/test.cpp
blob: 015b2c474151170f45cc8cab43e390291ba7eeb1 (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
// $Id$

#include "HelloS.h"
#include "ace/Argv_Type_Converter.h"

ACE_RCSID (Reference_Counting,
           test,
           "$Id$")

class Hello_impl :
  virtual public POA_Hello
{
public:
  Hello_impl ()
  {
    ACE_DEBUG ((LM_DEBUG, "Hello_impl::Hello_impl()\n"));
  }

  ~Hello_impl ()
  {
    ACE_DEBUG ((LM_DEBUG, "Hello_impl::~Hello_impl()\n"));
  }

  virtual void moo (
      ACE_ENV_SINGLE_ARG_DECL_NOT_USED
    )
    ACE_THROW_SPEC ((
      CORBA::SystemException
    ))
  {
  }
};

CORBA::ULong
getRefCount (PortableServer::ServantBase * sb ACE_ENV_ARG_DECL)
{
  return sb->_refcount_value (ACE_ENV_SINGLE_ARG_PARAMETER);
}

int
ACE_TMAIN (int argc, ACE_TCHAR * argv[])
{
  ACE_Argv_Type_Converter convert (argc, argv);

  ACE_TRY_NEW_ENV
    {
      CORBA::ORB_var orb =
        CORBA::ORB_init (convert.get_argc(), convert.get_ASCII_argv(), "" ACE_ENV_ARG_PARAMETER);
      ACE_TRY_CHECK;

      CORBA::Object_var poa_object =
        orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER);
      ACE_TRY_CHECK;

      PortableServer::POA_var poa =
        PortableServer::POA::_narrow (poa_object.in () ACE_ENV_ARG_PARAMETER);
      ACE_TRY_CHECK;

      if (CORBA::is_nil (poa.in ()))
        ACE_ERROR_RETURN ((LM_ERROR,
                           " (%P|%t) Panic: nil RootPOA\n"),
                          1);

      Hello_impl * h = 0;
      ACE_NEW_RETURN (h,Hello_impl, 1);

      CORBA::ULong before_act = h->_refcount_value (ACE_ENV_SINGLE_ARG_PARAMETER);
      ACE_TRY_CHECK;

      ACE_DEBUG ((LM_DEBUG, "Before activation: %d\n", before_act));

      PortableServer::ObjectId_var oid = poa->activate_object (h ACE_ENV_ARG_PARAMETER);
      ACE_TRY_CHECK;

      CORBA::ULong after_act = h->_refcount_value (ACE_ENV_SINGLE_ARG_PARAMETER);
      ACE_TRY_CHECK;

      ACE_DEBUG ((LM_DEBUG, "After activation: %d\n", after_act));
        {
          /*
           * C++ Language Mapping (formal/03-06-03), section 1.37.3 (Servant
           * Memory Management Considerations), first bullet on page 1-136:
           *
           *   POA::id_to_servant returns a Servant. The POA invokes _add_ref
           *   once on the Servant before returning it; the caller of
           *   id_to_servant is responsible for invoking _remove_ref on the
           *   returned servant when it is finished with it.
           */

          CORBA::ULong refCountBeforeIdToServant =
            h->_refcount_value (ACE_ENV_SINGLE_ARG_PARAMETER);
          ACE_TRY_CHECK;

          ACE_DEBUG ((LM_DEBUG, "Before id_to_servant:  %d\n", refCountBeforeIdToServant));

          PortableServer::ServantBase_var srv = poa->id_to_servant (oid.in() ACE_ENV_ARG_PARAMETER);
          ACE_TRY_CHECK;

          CORBA::ULong refCountAfterIdToServant =
            srv->_refcount_value (ACE_ENV_SINGLE_ARG_PARAMETER);;
          ACE_TRY_CHECK;

          ACE_DEBUG ((LM_DEBUG, "After id_to_servant:  %d\n", refCountAfterIdToServant));

           /*
           * According to the above quote, this assertion shall be true.
           */
          ACE_ASSERT (refCountAfterIdToServant == refCountBeforeIdToServant + 1);

          /*
           * At the end of this scope, "srv" is destructed, which decrements
           * the servant's reference count.
           */
        }

      CORBA::ULong before_deact = h->_refcount_value (ACE_ENV_SINGLE_ARG_PARAMETER);
      ACE_TRY_CHECK;

      ACE_DEBUG ((LM_DEBUG, "Before deactivate_object: %d\n", before_deact));

      poa->deactivate_object (oid.in() ACE_ENV_ARG_PARAMETER);
      ACE_TRY_CHECK;

      /*
       * Because id_to_servant did not increment the reference count, but
       * the reference count was decremented by the "srv" destructor, the
       * reference count, using TAO 1.4.5, is now 0, and the servant has
       * been destructed. So the following will crash, despite being
       * correct.
       */

      CORBA::ULong after_deact = h->_refcount_value (ACE_ENV_SINGLE_ARG_PARAMETER);
      ACE_TRY_CHECK;

      ACE_DEBUG ((LM_DEBUG, "After deactivate_object: %d\n", after_deact));

      h->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER);
      ACE_TRY_CHECK;

      orb->shutdown (1
                     ACE_ENV_ARG_PARAMETER);
      ACE_TRY_CHECK;

      orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
      ACE_TRY_CHECK;
    }
  ACE_CATCHANY
    {
      ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
                           "Exception caught:");
      return 1;
    }
  ACE_ENDTRY;

  return 0;
}