source: trunk/FACT++/src/EventImp.cc @ 10183

Last change on this file since 10183 was 10183, checked in by tbretz, 10 years ago
New import.
File size: 6.6 KB
Line 
1// **************************************************************************
2/** @class EventImp
3
4@brief A general base-class describing events issues in a state machine
5
6@section General purpose
7
8The general purpose of this class is to describe an event which can
9occur in one of our StateMachines. It provides pointers to data
10associated with the event, a target state and stores the states in which
11issuing this event is allowed. The target state might be negative to
12describe that no transition of the state is requested.
13
14Such an event canjust be a description of an event, but can also be
15an issued event which already contain data.
16
17The format can, but need not, contain the format of the data area.
18As a rule, it should follow the format also used in the DIM network.
19
20
21@section Assigning functions to an event
22
23To any event a function call can be assigned. Thanks to boost::bind there
24are various and different very powerful ways to do that.
25
26The function assigned with AssignFunction must return int. When it is
27executed it is given a const reference of the current event as an argument,
28i.e. if you want to get such a reference in your function, you can reference
29it using the placeholder _1. (Remark: it is allowe to omit the _1 placeholder
30if no reference to the EventImp object is needed)
31
32A few examples:
33
34\code
35   int function(const EventImp &evt, int i, const char *txt) { return i; }
36
37   EventImp evt;
38   evt.AssignFunction(boost::bind(function, _1, 7, "hallo"));
39   cout << evt.Exec() << endl;
40   // 7
41\endcode
42
43When the function is executed later via ExecFunc() in will get a reference
44to the executing EventImp as its first argument (indicated by '_1'), it will
45get 7 and "hallo" as second and third argument.
46
47\code
48   int function(int i, const char *txt, const EventImp &evt) { return i; }
49
50   EventImp evt;
51   evt.AssignFunction(boost::bind(function, 7, "hallo", _1));
52   cout << evt.Exec() << endl;
53   // 7
54\endcode
55
56Is the same example than the one above, but the arguments are in a different
57order.
58
59\code
60   class A
61   {
62      int function(const EventImp &evt, int i, const char *txt)
63      {
64         cout << this << endl; return i;
65      }
66   };
67
68   A a;
69
70   EventImp evt;
71   evt.AssignFunction(boost::bind(&A::function, &a, _1, 7, "hallo"));
72   cout << evt.Exec() << endl;
73   // &a
74   // 7
75\endcode
76
77The advanatge of boost::bind is that it also works for member functions
78of classes. In this case the first argument after the function-pointer
79\b must be a pointer to a valid class-object. This can also be \em this
80if called from within a class object.
81
82Also note that everything (as usual) which is not a reference is copied
83when the bind function is invoked. If you want to distribute a reference
84instead use ref(something), like
85
86\code
87   int function(int &i)  { return i; }
88
89   int j = 5;
90   EventImp evt;
91   evt.AssignFunction(bind(function, ref(j));
92   j = 7;
93   cout << evt.Exec() << endl;
94   // 7
95\endcode
96
97Note, that you are responsible for the validity, that means: Do not
98destroy your object (eg. reference to j) while bind might still be called
99later, or a pointer to \em this.
100
101@section References
102   - <A HREF="http://www.boost.org/doc/libs/1_45_0/libs/bind/bind.html">boost::bind (V1.45.0)</A>
103
104@todo
105   Add link to DIM format
106
107*/
108// **************************************************************************
109#include "EventImp.h"
110
111#include <sstream>
112
113#include "Time.h"
114
115using namespace std;
116
117// --------------------------------------------------------------------------
118//
119//! Copy the contents of an EventImp (fTargetState, fAllowedStates and
120//!  fFunction)
121//
122EventImp::EventImp(const EventImp &cmd) :
123    fTargetState(cmd.fTargetState), fAllowedStates(cmd.fAllowedStates),
124    fFunction(cmd.fFunction)
125{
126}
127
128// --------------------------------------------------------------------------
129//
130//! If the state is 0 or positive add it to fAllowedStates
131//!
132//! @param state
133//!     The state which should be added
134//
135void EventImp::AddAllowedState(int state)
136{
137    if (state>=0)
138        fAllowedStates.push_back(state);
139}
140
141// --------------------------------------------------------------------------
142//
143//! Add all states in the string to fAllowedStates.
144//!
145//! @param states
146//!    A string containing the states. They can either be separated by
147//!    whitespaces or commas, e.g. "1 2 3 4" or "1, 7, 9, 10". Note that
148//!    no real consistency check is done.
149//
150void EventImp::AddAllowedStates(const char *states)
151{
152    stringstream stream(states);
153
154    const bool sep = stream.str().find(',')==string::npos;
155
156    string buffer;
157    while (getline(stream, buffer, sep ? ' ' : ','))
158        AddAllowedState(atoi(buffer.c_str()));
159}
160
161// --------------------------------------------------------------------------
162//
163//! Return whether the given state is in the list of allowed states.
164//!
165//! @param state
166//!    The state to look for in fAllowedStates
167//!
168//! @returns
169//!    If the given state is negative returns false. If the list of allowed
170//!    states is empty return true. Otherwise return whether the state
171//!    is found in fAllowedList or not.
172//
173bool EventImp::IsStateAllowed(int state) const
174{
175    // States with negative values are internal states and are
176    // never allowed
177    if (state<0)
178        return false;
179
180    // In case no allowed state is explicitly set
181    // all positive states are allowed
182    if (fAllowedStates.size()==0)
183        return true;
184
185    return find(fAllowedStates.begin(), fAllowedStates.end(), state)!=fAllowedStates.end();
186}
187
188// --------------------------------------------------------------------------
189//
190//! Print the contents of the event to the given stream.
191//!
192//! @param out
193//!    An ostream to which the output should be redirected.
194//!
195void EventImp::Print(ostream &out) const
196{
197    out << " \xc2\xb7 ";
198
199    const string str = GetName();
200    if (!str.empty())
201        out << str;
202
203    const string fmt = GetFormat();
204    if (!fmt.empty())
205        out << "[" << fmt << "]";
206
207    out << ":";
208
209    for (unsigned int i=0; i<fAllowedStates.size(); i++)
210        out << " " << fAllowedStates[i];
211
212    if (fTargetState<0)
213        out << " [conf]";
214    else
215        out << " [trans->" << fTargetState << "]";
216
217    const Time tm = GetTime();
218
219    const bool t = tm!=Time::None && tm!=Time(1970,1,1);
220    const bool s = GetSize()>0;
221
222    if (s || t)
223        out << "(";
224    if (t)
225        out << tm.GetAsStr();
226    if (s && t)
227        out << "/";
228    if (s)
229        out << "size=" << GetSize();
230    if (s || t)
231        out << ")";
232    out << endl;
233}
234
235// --------------------------------------------------------------------------
236//
237//! Calls Print(std::cout)
238//
239void EventImp::Print() const
240{
241    Print(cout);
242}
Note: See TracBrowser for help on using the repository browser.