Defining 5 output slots in the constructor (Matthieu)
[u/mrichter/AliRoot.git] / HLT / trigger / AliHLTGlobalTriggerWrapper.cxx
CommitLineData
81d62bb4 1// $Id: $
2/**************************************************************************
3 * This file is property of and copyright by the ALICE HLT Project *
4 * ALICE Experiment at CERN, All rights reserved. *
5 * *
6 * Primary Authors: Artur Szostak <artursz@iafrica.com> *
7 * for The ALICE HLT Project. *
8 * *
9 * Permission to use, copy, modify and distribute this software and its *
10 * documentation strictly for non-commercial purposes is hereby granted *
11 * without fee, provided that the above copyright notice appears in all *
12 * copies and that both the copyright notice and this permission notice *
13 * appear in the supporting documentation. The authors make no claims *
14 * about the suitability of this software for any purpose. It is *
15 * provided "as is" without express or implied warranty. *
16 **************************************************************************/
17
18/// @file AliHLTGlobalTriggerWrapper.cxx
19/// @author Artur Szostak <artursz@iafrica.com>
20/// @date 28 Oct 2009
21/// @brief Implementation of the AliHLTGlobalTriggerWrapper interface class.
22///
23/// The AliHLTGlobalTriggerWrapper class is used to interface with an interpreted
24/// class deriving from AliHLTGlobalTrigger. This is used when the global trigger
25/// component is using CINT to interpret the trigger logic. The wrapper is necessary
26/// to be able to call interpreted code from compiled code.
27
28#include "AliHLTGlobalTriggerWrapper.h"
29#include "TArrayL64.h"
30#include "TClass.h"
31#include "TInterpreter.h"
32
33#ifdef R__BUILDING_CINT7
34#include "cint7/Api.h"
35#else
36#include "Api.h"
37#endif
38
39ClassImp(AliHLTGlobalTriggerWrapper)
40
41
325e5e42 42namespace
43{
44 /// Variable to store the error message if an error occured in CINT when interpreting code.
45 TString gCINTErrorMessage = "";
46
47 /**
48 * This routine is the callback for the CINT interpreter when it finds a syntax error
49 * in the source code generated by the AliHLTGlobalTriggerComponent class.
50 */
51 void AliHLTOnErrorInCINT(char* message)
52 {
53 gCINTErrorMessage += message;
54 }
55
56} // end of namespace
57
58
81d62bb4 59AliHLTGlobalTriggerWrapper::AliHLTGlobalTriggerWrapper(const char* classname) :
60 AliHLTGlobalTrigger(),
61 AliHLTLogging(),
62 fClass(NULL),
63 fObject(NULL),
64 fFillFromMenuCall(),
65 fNewEventCall(),
66 fAddCall(),
67 fCalculateTriggerDecisionCall(),
68 fGetCountersCall(),
325e5e42 69 fSetCountersCall(),
70 fCallFailed(false)
81d62bb4 71{
72 // The default constructor.
73
74 fClass = TClass::GetClass(classname);
75 if (fClass == NULL)
76 {
77 HLTError("Could not find class information for '%s'.", classname);
78 return;
79 }
80 fFillFromMenuCall.InitWithPrototype(fClass, "FillFromMenu", "const AliHLTTriggerMenu&");
81 if (not fFillFromMenuCall.IsValid())
82 {
83 HLTError("Could not initialise method call object for class '%s' and method FillFromMenu.", classname);
84 return;
85 }
86 fNewEventCall.InitWithPrototype(fClass, "NewEvent", " "); // Must have single whitespace in last parameter or we get a segfault in G__interpret_func.
87 if (not fNewEventCall.IsValid())
88 {
89 HLTError("Could not initialise method call object for class '%s' and method NewEvent.", classname);
90 return;
91 }
92 fAddCall.InitWithPrototype(fClass, "Add", "const TObject*, const AliHLTComponentDataType&, AliHLTUInt32_t");
93 if (not fAddCall.IsValid())
94 {
95 HLTError("Could not initialise method call object for class '%s' and method Add.", classname);
96 return;
97 }
98 fCalculateTriggerDecisionCall.InitWithPrototype(fClass, "CalculateTriggerDecision", "AliHLTTriggerDomain&, TString&");
99 if (not fCalculateTriggerDecisionCall.IsValid())
100 {
101 HLTError("Could not initialise method call object for class '%s' and method CalculateTriggerDecision.", classname);
102 return;
103 }
104 fGetCountersCall.InitWithPrototype(fClass, "GetCounters", " "); // Must have single whitespace in last parameter or we get a segfault in G__interpret_func.
105 if (not fGetCountersCall.IsValid())
106 {
107 HLTError("Could not initialise method call object for class '%s' and method GetCounters.", classname);
108 return;
109 }
110 fSetCountersCall.InitWithPrototype(fClass, "SetCounters", "TArrayL64&");
111 if (not fSetCountersCall.IsValid())
112 {
113 HLTError("Could not initialise method call object for class '%s' and method SetCounters.", classname);
114 return;
115 }
116 fObject = fClass->New();
117 if (fObject == NULL)
118 {
119 HLTError("Could not create a new object of type '%s'.", classname);
120 }
325e5e42 121
f2655396 122 // The following is a workaround for casting void* to void (*)(), i.e. a pointer to object to
123 // a pointer to function. Unfortunately the G__set_errmsgcallback routine interface is defined
124 // using a pointer to object so this workaround is necessary.
125 // We check that the two types are the same size. If they are not then such an operation is
126 // unsafe on the platform on which we are running and will not be performed.
127 union
128 {
129 void* fPtr;
130 void (*fFuncPtr)(char*);
131 };
132 fFuncPtr = AliHLTOnErrorInCINT;
133 if (sizeof(fPtr) == sizeof(fFuncPtr))
134 {
135 G__set_errmsgcallback(fPtr);
136 }
137 else
138 {
139 HLTWarning("On this platform a pointer to function and pointer to object are different sizes."
140 " For this reason we cannot use the G__set_errmsgcallback CINT API call in a safe way so all"
141 " error messages generated by CINT will not be captured or logged in the HLT system."
142 );
143 }
81d62bb4 144}
145
146
147AliHLTGlobalTriggerWrapper::~AliHLTGlobalTriggerWrapper()
148{
149 // Default destructor.
150
151 fClass->Destructor(fObject);
f0da6a36 152 G__set_errmsgcallback(NULL);
81d62bb4 153}
154
155
156void AliHLTGlobalTriggerWrapper::FillFromMenu(const AliHLTTriggerMenu& menu)
157{
158 // Fills internal values from the trigger menu.
159
325e5e42 160 fCallFailed = false;
81d62bb4 161 struct Params
162 {
163 const void* fMenu;
164 } params;
165 params.fMenu = &menu;
166 fFillFromMenuCall.SetParamPtrs(&params, 1);
325e5e42 167 gCINTErrorMessage = "";
81d62bb4 168 fFillFromMenuCall.Execute(fObject);
325e5e42 169 if (gCINTErrorMessage != "")
81d62bb4 170 {
325e5e42 171 fCallFailed = true;
172 HLTError(gCINTErrorMessage.Data());
173 HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
81d62bb4 174 }
175}
176
177
178void AliHLTGlobalTriggerWrapper::NewEvent()
179{
180 // Clears the internal buffers for a new event.
181
325e5e42 182 fCallFailed = false;
183 gCINTErrorMessage = "";
81d62bb4 184 fNewEventCall.Execute(fObject);
325e5e42 185 if (gCINTErrorMessage != "")
81d62bb4 186 {
325e5e42 187 fCallFailed = true;
188 HLTError(gCINTErrorMessage.Data());
189 HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
81d62bb4 190 }
191}
192
193
194void AliHLTGlobalTriggerWrapper::Add(
195 const TObject* object, const AliHLTComponentDataType& type,
196 AliHLTUInt32_t spec
197 )
198{
199 // Adds parameters from the object to the internal buffers and variables.
200
325e5e42 201 fCallFailed = false;
81d62bb4 202 struct Params
203 {
204 const void* fObj;
205 const void* fType;
206 long fSpec;
207 } params;
208 params.fObj = object;
209 params.fType = &type;
210 params.fSpec = spec;
211 fAddCall.SetParamPtrs(&params, 3);
325e5e42 212 gCINTErrorMessage = "";
81d62bb4 213 fAddCall.Execute(fObject);
325e5e42 214 if (gCINTErrorMessage != "")
81d62bb4 215 {
325e5e42 216 fCallFailed = true;
217 HLTError(gCINTErrorMessage.Data());
218 HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
81d62bb4 219 }
220}
221
222
223bool AliHLTGlobalTriggerWrapper::CalculateTriggerDecision(AliHLTTriggerDomain& domain, TString& description)
224{
225 // Calculates the global trigger decision.
226
325e5e42 227 fCallFailed = false;
81d62bb4 228 struct Params
229 {
230 const void* fDomain;
231 const void* fDesc;
232 } params;
233 params.fDomain = &domain;
234 params.fDesc = &description;
235 fCalculateTriggerDecisionCall.SetParamPtrs(&params, 2);
236 Long_t retval;
325e5e42 237 gCINTErrorMessage = "";
81d62bb4 238 fCalculateTriggerDecisionCall.Execute(fObject, retval);
325e5e42 239 if (gCINTErrorMessage != "")
81d62bb4 240 {
325e5e42 241 fCallFailed = true;
242 HLTError(gCINTErrorMessage.Data());
243 HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
244 return false;
81d62bb4 245 }
246 return bool(retval);
247}
248
249
250const TArrayL64& AliHLTGlobalTriggerWrapper::GetCounters() const
251{
252 // Returns the internal counter array.
253
254 Long_t retval = 0x0;
325e5e42 255 gCINTErrorMessage = "";
81d62bb4 256 fGetCountersCall.Execute(fObject, retval);
325e5e42 257 if (gCINTErrorMessage != "")
81d62bb4 258 {
325e5e42 259 fCallFailed = true;
260 HLTError(gCINTErrorMessage.Data());
261 HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
81d62bb4 262 }
263 static const TArrayL64 emptyArray;
264 const TArrayL64* ptr = &emptyArray; // Make sure we do not return a NULL pointer.
265 if (retval != 0x0) ptr = reinterpret_cast<const TArrayL64*>(retval);
266 return *ptr;
267}
268
269
270void AliHLTGlobalTriggerWrapper::SetCounters(const TArrayL64& counters)
271{
272 // Fills the internal counter array with new values.
273
325e5e42 274 fCallFailed = false;
81d62bb4 275 struct Params
276 {
277 const void* fCounters;
278 } params;
279 params.fCounters = &counters;
280 fSetCountersCall.SetParamPtrs(&params, 1);
325e5e42 281 gCINTErrorMessage = "";
81d62bb4 282 fSetCountersCall.Execute(fObject);
325e5e42 283 if (gCINTErrorMessage != "")
81d62bb4 284 {
325e5e42 285 fCallFailed = true;
286 HLTError(gCINTErrorMessage.Data());
287 HLTFatal("Error interpreting the code for class '%s' at line %d.", fClass->GetName(), G__lasterror_linenum());
81d62bb4 288 }
289}
290
291
292bool AliHLTGlobalTriggerWrapper::IsValid() const
293{
294 // Checks if the wrapper class was initialised correctly.
295
296 return fClass != NULL and fObject != NULL and fFillFromMenuCall.IsValid()
297 and fNewEventCall.IsValid() and fAddCall.IsValid()
298 and fCalculateTriggerDecisionCall.IsValid();
299}
300