summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/Event/EC_ProxyConsumer.h
blob: c6ec73de326545671ae77e299a382b546e45a1ba (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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// -*- C++ -*-
/**
 *  @file   EC_ProxyConsumer.h
 *
 *  @author Carlos O'Ryan (coryan@cs.wustl.edu)
 *
 * Based on previous work by Tim Harrison (harrison@cs.wustl.edu) and
 * other members of the DOC group. More details can be found in:
 *
 * http://doc.ece.uci.edu/~coryan/EC/index.html
 */

#ifndef TAO_EC_PROXYCONSUMER_H
#define TAO_EC_PROXYCONSUMER_H

#include /**/ "ace/pre.h"

#include /**/ "orbsvcs/Event/event_serv_export.h"

#include "orbsvcs/RtecEventChannelAdminS.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

TAO_BEGIN_VERSIONED_NAMESPACE_DECL

class TAO_EC_Event_Channel_Base;
class TAO_EC_ProxyPushSupplier;
class TAO_EC_Supplier_Filter;

/**
 * @class TAO_EC_ProxyPushConsumer
 *
 * @brief ProxyPushConsumer
 *
 * Implement the RtecEventChannelAdmin::ProxyPushConsumer interface,
 * remember that this class is used to communicate with a
 * PushSupplier, so, in effect, this is the ambassador for a
 * supplier inside the event channel.
 *
 * <H2>Memory Management</H2>
 * It makes a copy of the SupplierQOS and the supplier object
 * reference.
 * It uses bind/unbind to control the lifetime of the
 * Supplier_Filter object.
 * The object commits suicide when disconnect_push_consumer() is
 * called.
 *
 * <H2>Locking</H2>
 * No provisions for locking, access must be serialized
 * externally.
 */
class TAO_RTEvent_Serv_Export TAO_EC_ProxyPushConsumer
{
public:
  typedef RtecEventChannelAdmin::ProxyPushConsumer Interface;
  typedef RtecEventChannelAdmin::ProxyPushConsumer_var _var_type;
  typedef RtecEventChannelAdmin::ProxyPushConsumer_ptr _ptr_type;

  /// constructor...
  TAO_EC_ProxyPushConsumer (TAO_EC_Event_Channel_Base* event_channel);

  /// destructor...
  virtual ~TAO_EC_ProxyPushConsumer (void);

  /// Activate in the POA
  virtual void activate (
          RtecEventChannelAdmin::ProxyPushConsumer_ptr &proxy)
    = 0;

  /// Deactivate from the POA
  virtual void deactivate (void);

  /// Disconnect this from
  virtual void disconnect_push_consumer () = 0;

  /// Return false if no supplier is connected...
  CORBA::Boolean is_connected (void) const;

  /// Return the consumer object reference. It returns nil() if it has
  /// not connected yet.
  RtecEventComm::PushSupplier_ptr supplier (void) const;

  /// The QoS (subscription) used to connect to the EC.
  const RtecEventChannelAdmin::SupplierQOS& publications (void) const;

  /**
   * Invoke the _non_existent() pseudo-operation on the supplier. If
   * it is disconnected then it returns true and sets the
   * @a disconnected flag.
   */
  CORBA::Boolean supplier_non_existent (CORBA::Boolean_out disconnected);

  /// Concrete implementations can use this methods to keep track of
  /// the consumers interested in this events.
  virtual void connected (TAO_EC_ProxyPushSupplier* supplier);
  virtual void reconnected (TAO_EC_ProxyPushSupplier* supplier);
  virtual void disconnected (TAO_EC_ProxyPushSupplier* supplier);

  /// Usually implemented as no-ops, but some configurations may
  /// require this methods.
  virtual void connected (TAO_EC_ProxyPushConsumer* consumer);
  virtual void reconnected (TAO_EC_ProxyPushConsumer* consumer);
  virtual void disconnected (TAO_EC_ProxyPushConsumer* consumer);

  /// The event channel is shutting down
  virtual void shutdown (void);

  /// The QoS (subscription) used to connect to the EC, assumes the
  /// locks are held, use with care!
  const RtecEventChannelAdmin::SupplierQOS& publications_i (void) const;

  /// Increment and decrement the reference count.
  CORBA::ULong _incr_refcnt (void);
  CORBA::ULong _decr_refcnt (void);


protected:
  /// Set the supplier, used by some implementations to change the
  /// policies used when invoking operations on the supplier.
  void supplier (RtecEventComm::PushSupplier_ptr supplier);
  void supplier_i (RtecEventComm::PushSupplier_ptr supplier);

  friend class TAO_EC_ProxyPushConsumer_Guard;
  // The guard needs access to the following protected methods.

  /// The private version (without locking) of is_connected().
  CORBA::Boolean is_connected_i (void) const;

  /// Return the current filter, assumes the locks are held.
  TAO_EC_Supplier_Filter *filter_i (void) const;

  /// Release the filter and the supplier
  void cleanup_i (void);

  /// The supplier admin, used for activation and memory management.
  TAO_EC_Event_Channel_Base* event_channel_;

  /// The locking strategy.
  ACE_Lock* lock_;

  /// The reference count.
  CORBA::ULong ec_refcount_;

  /// The supplier....
  RtecEventComm::PushSupplier_var supplier_;

  /// If the flag is not zero then we are connected, notice that the
  /// supplier can be nil.
  bool connected_;

  /// The publication and QoS information...
  RtecEventChannelAdmin::SupplierQOS qos_;

  /// Store the default POA.
  PortableServer::POA_var default_POA_;

  /// The strategy to do filtering close to the supplier
  TAO_EC_Supplier_Filter* filter_;

private:
  /// Template method hooks.
  virtual void shutdown_hook (void);
  virtual void refcount_zero_hook (void);

  virtual PortableServer::ObjectId object_id (void) = 0;
};

// ****************************************************************

/**
 * @class TAO_EC_ProxyPushConsumer_Guard
 *
 * @brief A Guard for the ProxyPushConsumer reference count
 *
 * This is a helper class used in the implementation of
 * ProxyPushConumer.  It provides a Guard mechanism to increment
 * the reference count on the proxy and its filter, eliminating
 * the need to hold mutexes during long operations.
 */
class TAO_RTEvent_Serv_Export TAO_EC_ProxyPushConsumer_Guard
{
public:
  /// Constructor
  TAO_EC_ProxyPushConsumer_Guard (ACE_Lock *lock,
                                  CORBA::ULong &refcount,
                                  TAO_EC_Event_Channel_Base *ec,
                                  TAO_EC_ProxyPushConsumer *proxy);

  /// Destructor
  ~TAO_EC_ProxyPushConsumer_Guard (void);

  /// Returns true if the reference count successfully acquired
  bool locked (void) const;

  TAO_EC_Supplier_Filter *filter;

private:
  /// The lock used to protect the reference count
  ACE_Lock *lock_;

  /// The reference count
  CORBA::ULong &refcount_;

  /// The event channel used to destroy the proxy
  // TAO_EC_Event_Channel_Base *event_channel_;

  /// The proxy whose lifetime is controlled by the reference count
  TAO_EC_ProxyPushConsumer *proxy_;

  /// This flag is set to true if the reference count was successfully
  /// acquired.
  bool locked_;
};

TAO_END_VERSIONED_NAMESPACE_DECL

#if defined (__ACE_INLINE__)
#include "orbsvcs/Event/EC_ProxyConsumer.inl"
#endif /* __ACE_INLINE__ */

#include /**/ "ace/post.h"

#endif /* TAO_EC_PROXYCONSUMER_H */