summaryrefslogtreecommitdiff
path: root/ACE/tests/Bug_2820_Regression_Test.cpp
blob: 020261857800690bad2b718d34c9c5da97e9ef81 (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
/**
 * @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);

  /// 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();

  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));
    }

  // Remove a reference for each time we explicitly increased it,
  // minus one time because the _var will take care of that.
  v->remove_reference();
  v->remove_reference();

  if (result == 0)
    {
      ACE_DEBUG ((LM_INFO,
		  ACE_TEXT("Test passed.  pre_notify refcount=%d,")
		  ACE_TEXT(" pos_notify=%d, pos_delete=%d\n"),
		  pre_notify_count, pos_notify_count, pos_release_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);
}

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