summaryrefslogtreecommitdiff
path: root/ACE/tests/Bug_2820_Regression_Test.cpp
blob: 9c61d4bde87a4373de24b72c9107f52fc70858fe (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
/**
 * @file Bug_2820_Regression_Test.cpp
 *
 * $Id$
 *
 * Verify that the event handler reference counting works correctly
 * when the reactor is destroyed.
 *
 * Pushing a notification through the reactor increments the reference
 * count on the target event handler.  Both dispatching and purging
 * the notification decrement the reference count.  However,
 * destroying the reactor used to not decrement the reference count.
 * This test reproduces the problem and serves as a regression for it.
 *
 * @author Carlos O'Ryan <coryan@atdesk.com>
 *
 */

#include "test_config.h"
#include "ace/Auto_Ptr.h"
#include "ace/Reactor.h"
#include "ace/Select_Reactor.h"

ACE_RCSID(tests,
          Bug_2820_Regression_Test, "$Id$")

/**
 * @class Simple_Handler
 *
 * @brief A simple event handler for the test
 *
 */
class Simple_Handler : public ACE_Event_Handler
{
public:
  /// Constructor
  Simple_Handler(ACE_Reactor * reactor);

  /// Destructor
  ~Simple_Handler();

  /// Receive (and ignore) the notifications
  virtual int handle_exception(ACE_HANDLE);
};

int
run_main (int, ACE_TCHAR *[])
{
  ACE_START_TEST (ACE_TEXT ("Bug_2820_Regression_Test"));

  int result = 0;

  auto_ptr<ACE_Reactor> reactor(
      new ACE_Reactor(new ACE_Select_Reactor, 1));

  ACE_Event_Handler_var v(
      new Simple_Handler(reactor.get()));

  ACE_Event_Handler::Reference_Count pre_notify_count =
    v->add_reference();

  int const notify_count = 4;
  for(int i = 0; i != notify_count; ++i)
    {
      reactor->notify(v.handler());
    }

  ACE_Event_Handler::Reference_Count pos_notify_count =
    v->add_reference();

  if(pos_notify_count != pre_notify_count + notify_count + 1)
    {
      result = -1;
      ACE_ERROR((LM_ERROR,
		 ACE_TEXT("Reference count should increase by %d.")
		 ACE_TEXT("  Initial count=%d, final count = %d\n"),
		 notify_count, pre_notify_count, pos_notify_count));
    }

  reactor.reset();

  // Reset the reactor in the event handler, since it is gone.p
  v->reactor(0);

  ACE_Event_Handler::Reference_Count pos_release_count =
    v->add_reference();

  // Only our explicit calls to add_reference() should be reflected in
  // the refence_count...
  if (pos_release_count != pre_notify_count + 2)
    {
      result = -1;
      ACE_ERROR((LM_ERROR,
		 ACE_TEXT("Reference count should have increased by 2.")
		 ACE_TEXT("  Initial count=%d, final count = %d\n"),
		 pre_notify_count, pos_release_count));
    }

  ACE_DEBUG ((LM_INFO,
	      ACE_TEXT("Ref count results.  pre_notify refcount=%d,")
	      ACE_TEXT(" pos_notify=%d, pos_delete=%d\n"),
	      pre_notify_count, pos_notify_count, pos_release_count));
  
  // Remove a reference for each time we explicitly increased it.
  v->remove_reference();
  v->remove_reference();
  ACE_Event_Handler::Reference_Count pos_remove_count =
      v->remove_reference();

  ACE_DEBUG ((LM_INFO,
	      ACE_TEXT("Ref count results.  pre_notify refcount=%d,")
	      ACE_TEXT(" pos_notify=%d, pos_delete=%d, pos_remove=%d\n"),
	      pre_notify_count, pos_notify_count, pos_release_count,
	      pos_remove_count));

  ACE_END_TEST;

  return result;
}

// ============================================

Simple_Handler::
Simple_Handler(
    ACE_Reactor * r)
  : ACE_Event_Handler(r)
{
  reference_counting_policy().value(
        ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
}

Simple_Handler::
~Simple_Handler()
{
}

int Simple_Handler::
handle_exception(ACE_HANDLE)
{
  return 0;
}