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
|
// -*- C++ -*-
//=============================================================================
/**
* @file LF_Event.h
*
* $Id$
*
* @author Carlos O'Ryan <coryan@uci.edu>
*/
//=============================================================================
#ifndef TAO_LF_EVENT_H
#define TAO_LF_EVENT_H
#include "ace/pre.h"
#include "TAO_Export.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
class TAO_LF_Follower;
/**
* @class TAO_LF_Event
*
* @brief Use the Leader/Follower loop to wait for one specific event.
*
* The Leader/Follower event loop is used to wait for incoming
* responses, as well as to wait for all the data to be flushed.
* This class encapsulates this event loop. It uses Template Method to
* parametrize the 'waited for' predicate (i.e. reply received or
* message sent.)
*
* @todo Implementing the Leader/Followers loop in this class, as
* well as the callbacks to communicate that an event has completed
* leads to excessive coupling. A better design would use a separate
* class to signal the events, that would allow us to remove the
* Leader/Followers logic from the ORB. However, that requires other
* major changes and it somewhat complicates the design.
*
*/
class TAO_Export TAO_LF_Event
{
public:
friend class TAO_Leader_Follower;
/// Constructor
TAO_LF_Event (void);
/// Destructor
virtual ~TAO_LF_Event (void);
/// Bind a follower
/**
* An event can be waited on by at most one follower thread, this
* method is used to bind the waiting thread to the event, in order
* to let the event signal any important state changes.
*
* @return -1 if the LF_Event is already bound, 0 otherwise
*/
int bind (TAO_LF_Follower *follower);
/// Unbind the follower
int unbind (void);
//@{
/** @name State management
*
* A Leader/Followers event goes through several states during its
* lifetime. We use an enum to represent those states and state
* changes are validated according to the rules below.
*
*/
enum {
/// The event is created, initial state can only move to
/// LFS_ACTIVE or LFS_CONNECTION_WAIT
LFS_IDLE,
/// The event is active, can change to any of the following
/// states, each of them is a final state
LFS_ACTIVE,
/// The event is waiting for connection completion. It can change
/// to the any of the following states, each of them being a final
/// state.
LFS_CONNECTION_WAIT,
/// The event has completed successfully
LFS_SUCCESS,
/// A failure has been detected while the event was active
LFS_FAILURE,
/// The event has timed out
LFS_TIMEOUT,
/// The connection was closed while the state was active
LFS_CONNECTION_CLOSED
};
/// Change the state
void state_changed (int new_state);
/// Return 1 if the condition was satisfied successfully, 0 if it
/// has not
int successful (void) const;
/// Return 1 if an error was detected while waiting for the
/// event
int error_detected (void) const;
//@}
/// Check if we should keep waiting.
int keep_waiting (void);
/// Reset the state, irrespective of the previous states
void reset_state (int new_state);
protected:
/// Validate the state change
void state_changed_i (int new_state);
private:
/// Check whether we have reached the final state..
int is_state_final (void);
/// Set the state.
void set_state (int new_state);
private:
/// The current state
int state_;
/// The bound follower thread
TAO_LF_Follower *follower_;
};
#if defined (__ACE_INLINE__)
# include "LF_Event.inl"
#endif /* __ACE_INLINE__ */
#include "ace/post.h"
#endif /* TAO_LF_EVENT_H */
|