File: | alld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h |
Warning: | line 398, column 7 Null pointer passed to 2nd parameter expecting 'nonnull' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // $Id: DTrackWireBased_factory.cc 5612 2009-10-15 20:51:25Z staylor $ | ||||||
2 | // | ||||||
3 | // File: DTrackWireBased_factory.cc | ||||||
4 | // Created: Wed Sep 3 09:33:40 EDT 2008 | ||||||
5 | // Creator: davidl (on Darwin harriet.jlab.org 8.11.1 i386) | ||||||
6 | // | ||||||
7 | |||||||
8 | |||||||
9 | #include <iostream> | ||||||
10 | #include <iomanip> | ||||||
11 | #include <set> | ||||||
12 | #include <cmath> | ||||||
13 | #include <mutex> | ||||||
14 | using namespace std; | ||||||
15 | |||||||
16 | #include "DTrackWireBased_factory.h" | ||||||
17 | #include <TRACKING/DTrackCandidate.h> | ||||||
18 | #include <TRACKING/DReferenceTrajectory.h> | ||||||
19 | #include <CDC/DCDCTrackHit.h> | ||||||
20 | #include <FDC/DFDCPseudo.h> | ||||||
21 | #include <SplitString.h> | ||||||
22 | |||||||
23 | #include <TROOT.h> | ||||||
24 | |||||||
25 | using namespace jana; | ||||||
26 | |||||||
27 | //------------------ | ||||||
28 | // CDCSortByRincreasing | ||||||
29 | //------------------ | ||||||
30 | bool CDCSortByRincreasing(const DCDCTrackHit* const &hit1, const DCDCTrackHit* const &hit2) { | ||||||
31 | // use the ring number to sort by R(decreasing) and then straw(increasing) | ||||||
32 | if(hit1->wire->ring == hit2->wire->ring){ | ||||||
33 | return hit1->wire->straw < hit2->wire->straw; | ||||||
34 | } | ||||||
35 | return hit1->wire->ring < hit2->wire->ring; | ||||||
36 | } | ||||||
37 | |||||||
38 | //------------------ | ||||||
39 | // FDCSortByZincreasing | ||||||
40 | //------------------ | ||||||
41 | bool FDCSortByZincreasing(const DFDCPseudo* const &hit1, const DFDCPseudo* const &hit2) { | ||||||
42 | // use the layer number to sort by Z(decreasing) and then wire(increasing) | ||||||
43 | if(hit1->wire->layer == hit2->wire->layer){ | ||||||
44 | return hit1->wire->wire < hit2->wire->wire; | ||||||
45 | } | ||||||
46 | return hit1->wire->layer < hit2->wire->layer; | ||||||
47 | } | ||||||
48 | |||||||
49 | //------------------ | ||||||
50 | // TRDSortByZincreasing | ||||||
51 | //------------------ | ||||||
52 | bool TRDSortByZincreasing(const DTRDPoint* const &hit1, const DTRDPoint* const &hit2) { | ||||||
53 | |||||||
54 | return hit1->detector < hit2->detector; | ||||||
55 | } | ||||||
56 | |||||||
57 | //------------------ | ||||||
58 | // GEMSortByZincreasing | ||||||
59 | //------------------ | ||||||
60 | bool GEMSortByZincreasing(const DGEMPoint* const &hit1, const DGEMPoint* const &hit2) { | ||||||
61 | |||||||
62 | return hit1->detector < hit2->detector; | ||||||
63 | } | ||||||
64 | |||||||
65 | //------------------ | ||||||
66 | // count_common_members | ||||||
67 | //------------------ | ||||||
68 | template<typename T> | ||||||
69 | static unsigned int count_common_members(vector<T> &a, vector<T> &b) | ||||||
70 | { | ||||||
71 | unsigned int n=0; | ||||||
72 | for(unsigned int i=0; i<a.size(); i++){ | ||||||
73 | for(unsigned int j=0; j<b.size(); j++){ | ||||||
74 | if(a[i]==b[j])n++; | ||||||
75 | } | ||||||
76 | } | ||||||
77 | |||||||
78 | return n; | ||||||
79 | } | ||||||
80 | |||||||
81 | bool DTrackWireBased_cmp(DTrackWireBased *a,DTrackWireBased *b){ | ||||||
82 | if (a->candidateid==b->candidateid) return a->mass()<b->mass(); | ||||||
83 | return a->candidateid<b->candidateid; | ||||||
84 | } | ||||||
85 | |||||||
86 | //------------------ | ||||||
87 | // init | ||||||
88 | //------------------ | ||||||
89 | jerror_t DTrackWireBased_factory::init(void) | ||||||
90 | { | ||||||
91 | fitter = NULL__null; | ||||||
92 | |||||||
93 | //DEBUG_HISTS = true; | ||||||
94 | DEBUG_HISTS = false; | ||||||
95 | DEBUG_LEVEL = 0; | ||||||
96 | |||||||
97 | gPARMS->SetDefaultParameter("TRKFIT:DEBUG_LEVEL",DEBUG_LEVEL); | ||||||
98 | |||||||
99 | SKIP_MASS_HYPOTHESES_WIRE_BASED=true; | ||||||
100 | gPARMS->SetDefaultParameter("TRKFIT:SKIP_MASS_HYPOTHESES_WIRE_BASED", | ||||||
101 | SKIP_MASS_HYPOTHESES_WIRE_BASED); | ||||||
102 | PROTON_MOM_THRESH=0.8; // GeV | ||||||
103 | gPARMS->SetDefaultParameter("TRKFIT:PROTON_MOM_THRESH", | ||||||
104 | PROTON_MOM_THRESH); | ||||||
105 | |||||||
106 | // Make list of mass hypotheses to use in fit | ||||||
107 | vector<int> hypotheses; | ||||||
108 | hypotheses.push_back(Positron); | ||||||
109 | hypotheses.push_back(PiPlus); | ||||||
110 | hypotheses.push_back(KPlus); | ||||||
111 | hypotheses.push_back(Proton); | ||||||
112 | hypotheses.push_back(Electron); | ||||||
113 | hypotheses.push_back(PiMinus); | ||||||
114 | hypotheses.push_back(KMinus); | ||||||
115 | hypotheses.push_back(AntiProton); | ||||||
116 | |||||||
117 | ostringstream locMassStream; | ||||||
118 | for(size_t loc_i = 0; loc_i < hypotheses.size(); ++loc_i) | ||||||
119 | { | ||||||
120 | locMassStream << hypotheses[loc_i]; | ||||||
121 | if(loc_i != (hypotheses.size() - 1)) | ||||||
122 | locMassStream << ","; | ||||||
123 | } | ||||||
124 | |||||||
125 | string HYPOTHESES = locMassStream.str(); | ||||||
126 | gPARMS->SetDefaultParameter("TRKFIT:HYPOTHESES", HYPOTHESES); | ||||||
127 | |||||||
128 | // Parse MASS_HYPOTHESES strings to make list of masses to try | ||||||
129 | hypotheses.clear(); | ||||||
130 | SplitString(HYPOTHESES, hypotheses, ","); | ||||||
131 | for(size_t loc_i = 0; loc_i < hypotheses.size(); ++loc_i) | ||||||
132 | { | ||||||
133 | if(ParticleCharge(Particle_t(hypotheses[loc_i])) > 0) | ||||||
134 | mass_hypotheses_positive.push_back(hypotheses[loc_i]); | ||||||
135 | else if(ParticleCharge(Particle_t(hypotheses[loc_i])) < 0) | ||||||
136 | mass_hypotheses_negative.push_back(hypotheses[loc_i]); | ||||||
137 | } | ||||||
138 | |||||||
139 | if(mass_hypotheses_positive.empty()){ | ||||||
140 | static once_flag pwarn_flag; | ||||||
141 | call_once(pwarn_flag, [](){ | ||||||
142 | jout << endl; | ||||||
143 | jout << "############# WARNING !! ################ " <<endl; | ||||||
144 | jout << "There are no mass hypotheses for positive tracks!" << endl; | ||||||
145 | jout << "Be SURE this is what you really want!" << endl; | ||||||
146 | jout << "######################################### " <<endl; | ||||||
147 | jout << endl; | ||||||
148 | }); | ||||||
149 | } | ||||||
150 | if(mass_hypotheses_negative.empty()){ | ||||||
151 | static once_flag nwarn_flag; | ||||||
152 | call_once(nwarn_flag, [](){ | ||||||
153 | jout << endl; | ||||||
154 | jout << "############# WARNING !! ################ " <<endl; | ||||||
155 | jout << "There are no mass hypotheses for negative tracks!" << endl; | ||||||
156 | jout << "Be SURE this is what you really want!" << endl; | ||||||
157 | jout << "######################################### " <<endl; | ||||||
158 | jout << endl; | ||||||
159 | }); | ||||||
160 | } | ||||||
161 | mNumHypPlus=mass_hypotheses_positive.size(); | ||||||
162 | mNumHypMinus=mass_hypotheses_negative.size(); | ||||||
163 | |||||||
164 | return NOERROR; | ||||||
165 | } | ||||||
166 | |||||||
167 | //------------------ | ||||||
168 | // brun | ||||||
169 | //------------------ | ||||||
170 | jerror_t DTrackWireBased_factory::brun(jana::JEventLoop *loop, int32_t runnumber) | ||||||
171 | { | ||||||
172 | // Get the geometry | ||||||
173 | DApplication* dapp=dynamic_cast<DApplication*>(loop->GetJApplication()); | ||||||
174 | geom = dapp->GetDGeometry(runnumber); | ||||||
175 | // Check for magnetic field | ||||||
176 | const DMagneticFieldMap *bfield=dapp->GetBfield(runnumber); | ||||||
177 | dIsNoFieldFlag = (dynamic_cast<const DMagneticFieldMapNoField*>(bfield) != NULL__null); | ||||||
| |||||||
178 | |||||||
179 | if(dIsNoFieldFlag
| ||||||
180 | //Setting this flag makes it so that JANA does not delete the objects in | ||||||
181 | //_data. This factory will manage this memory. | ||||||
182 | //This is all of these pointers are just copied from the "StraightLine" | ||||||
183 | //factory, and should not be re-deleted. | ||||||
184 | SetFactoryFlag(NOT_OBJECT_OWNER); | ||||||
185 | } | ||||||
186 | else{ | ||||||
187 | ClearFactoryFlag(NOT_OBJECT_OWNER); //This factory will create it's own obje | ||||||
188 | } | ||||||
189 | |||||||
190 | // set up reference trajectory | ||||||
191 | rt = new DReferenceTrajectory(bfield); | ||||||
192 | rt->SetDGeometry(geom); | ||||||
193 | |||||||
194 | // Get pointer to DTrackFitter object that actually fits a track | ||||||
195 | vector<const DTrackFitter *> fitters; | ||||||
196 | loop->Get(fitters); | ||||||
197 | |||||||
198 | if(fitters.size()<1){ | ||||||
199 | _DBG_std::cerr<<"libraries/TRACKING/DTrackWireBased_factory.cc" <<":"<<199<<" "<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<<endl; | ||||||
200 | return RESOURCE_UNAVAILABLE; | ||||||
201 | } | ||||||
202 | |||||||
203 | // Drop the const qualifier from the DTrackFitter pointer (I'm surely going to hell for this!) | ||||||
204 | fitter = const_cast<DTrackFitter*>(fitters[0]); | ||||||
205 | |||||||
206 | // Warn user if something happened that caused us NOT to get a fitter object pointer | ||||||
207 | if(!fitter){ | ||||||
208 | _DBG_std::cerr<<"libraries/TRACKING/DTrackWireBased_factory.cc" <<":"<<208<<" "<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<<endl; | ||||||
209 | return RESOURCE_UNAVAILABLE; | ||||||
210 | } | ||||||
211 | |||||||
212 | USE_HITS_FROM_CANDIDATE=false; | ||||||
213 | gPARMS->SetDefaultParameter("TRKFIT:USE_HITS_FROM_CANDIDATE", | ||||||
214 | USE_HITS_FROM_CANDIDATE); | ||||||
215 | |||||||
216 | MIN_FIT_P = 0.050; // GeV | ||||||
217 | gPARMS->SetDefaultParameter("TRKFIT:MIN_FIT_P", MIN_FIT_P, "Minimum fit momentum in GeV/c for fit to be considered successful"); | ||||||
218 | |||||||
219 | if(DEBUG_HISTS){ | ||||||
220 | dapp->Lock(); | ||||||
221 | |||||||
222 | // Histograms may already exist. (Another thread may have created them) | ||||||
223 | // Try and get pointers to the existing ones. | ||||||
224 | |||||||
225 | |||||||
226 | dapp->Unlock(); | ||||||
227 | } | ||||||
228 | |||||||
229 | // Get the particle ID algorithms | ||||||
230 | loop->GetSingle(dPIDAlgorithm); | ||||||
231 | |||||||
232 | // Outer detector geometry parameters | ||||||
233 | if (geom->GetDIRCZ(dDIRCz)==false) dDIRCz=1000.; | ||||||
234 | geom->GetFCALZ(dFCALz); | ||||||
235 | vector<double>tof_face; | ||||||
236 | geom->Get("//section/composition/posXYZ[@volume='ForwardTOF']/@X_Y_Z", | ||||||
237 | tof_face); | ||||||
238 | vector<double>tof_plane; | ||||||
239 | geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='0']", tof_plane); | ||||||
240 | dTOFz=tof_face[2]+tof_plane[2]; | ||||||
241 | geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='1']", tof_plane); | ||||||
242 | dTOFz+=tof_face[2]+tof_plane[2]; | ||||||
243 | dTOFz*=0.5; // mid plane between tof planes | ||||||
244 | |||||||
245 | // Get start counter geometry; | ||||||
246 | if (geom->GetStartCounterGeom(sc_pos,sc_norm)){ | ||||||
247 | // Create vector of direction vectors in scintillator planes | ||||||
248 | for (int i=0;i<30;i++){ | ||||||
249 | vector<DVector3>temp; | ||||||
250 | for (unsigned int j=0;j<sc_pos[i].size()-1;j++){ | ||||||
251 | double dx=sc_pos[i][j+1].x()-sc_pos[i][j].x(); | ||||||
252 | double dy=sc_pos[i][j+1].y()-sc_pos[i][j].y(); | ||||||
253 | double dz=sc_pos[i][j+1].z()-sc_pos[i][j].z(); | ||||||
254 | temp.push_back(DVector3(dx/dz,dy/dz,1.)); | ||||||
255 | } | ||||||
256 | sc_dir.push_back(temp); | ||||||
257 | } | ||||||
258 | SC_END_NOSE_Z=sc_pos[0][12].z(); | ||||||
259 | SC_BARREL_R=sc_pos[0][0].Perp(); | ||||||
260 | SC_PHI_SECTOR1=sc_pos[0][0].Phi(); | ||||||
261 | } | ||||||
262 | |||||||
263 | return NOERROR; | ||||||
264 | } | ||||||
265 | |||||||
266 | //------------------ | ||||||
267 | // evnt | ||||||
268 | //------------------ | ||||||
269 | jerror_t DTrackWireBased_factory::evnt(JEventLoop *loop, uint64_t eventnumber) | ||||||
270 | { | ||||||
271 | |||||||
272 | if(!fitter)return NOERROR; | ||||||
273 | |||||||
274 | if(dIsNoFieldFlag){ | ||||||
275 | //Clear previous objects: | ||||||
276 | //JANA doesn't do it because NOT_OBJECT_OWNER was set | ||||||
277 | //It DID delete them though, in the "StraightLine" factory | ||||||
278 | _data.clear(); | ||||||
279 | |||||||
280 | vector<const DTrackWireBased*> locWireBasedTracks; | ||||||
281 | loop->Get(locWireBasedTracks, "StraightLine"); | ||||||
282 | for(size_t loc_i = 0; loc_i < locWireBasedTracks.size(); ++loc_i) | ||||||
283 | _data.push_back(const_cast<DTrackWireBased*>(locWireBasedTracks[loc_i])); | ||||||
284 | return NOERROR; | ||||||
285 | } | ||||||
286 | |||||||
287 | // Get candidates and hits | ||||||
288 | vector<const DTrackCandidate*> candidates; | ||||||
289 | loop->Get(candidates); | ||||||
290 | |||||||
291 | if (candidates.size()==0) return NOERROR; | ||||||
292 | |||||||
293 | // Loop over candidates | ||||||
294 | for(unsigned int i=0; i<candidates.size(); i++){ | ||||||
295 | const DTrackCandidate *candidate = candidates[i]; | ||||||
296 | |||||||
297 | // Skip candidates with momentum below some cutoff | ||||||
298 | if (candidate->momentum().Mag()<MIN_FIT_P){ | ||||||
299 | continue; | ||||||
300 | } | ||||||
301 | |||||||
302 | if (SKIP_MASS_HYPOTHESES_WIRE_BASED){ | ||||||
303 | rt->Reset(); | ||||||
304 | rt->q = candidate->charge(); | ||||||
305 | |||||||
306 | DoFit(i,candidate,rt,loop,ParticleMass(PiPlus)); | ||||||
307 | // Only do fit for proton mass hypothesis for low momentum particles | ||||||
308 | if (candidate->momentum().Mag()<PROTON_MOM_THRESH){ | ||||||
309 | rt->Reset(); | ||||||
310 | DoFit(i,candidate,rt,loop,ParticleMass(Proton)); | ||||||
311 | } | ||||||
312 | } | ||||||
313 | else{ | ||||||
314 | // Choose list of mass hypotheses based on charge of candidate | ||||||
315 | vector<int> mass_hypotheses; | ||||||
316 | if(candidate->charge()<0.0){ | ||||||
317 | mass_hypotheses = mass_hypotheses_negative; | ||||||
318 | }else{ | ||||||
319 | mass_hypotheses = mass_hypotheses_positive; | ||||||
320 | } | ||||||
321 | |||||||
322 | if ((!isfinite(candidate->momentum().Mag())) || (!isfinite(candidate->position().Mag()))) | ||||||
323 | _DBG_std::cerr<<"libraries/TRACKING/DTrackWireBased_factory.cc" <<":"<<323<<" " << "Invalid seed data for event "<< eventnumber <<"..."<<endl; | ||||||
324 | |||||||
325 | // Loop over potential particle masses | ||||||
326 | for(unsigned int j=0; j<mass_hypotheses.size(); j++){ | ||||||
327 | if(DEBUG_LEVEL>1){_DBG__std::cerr<<"libraries/TRACKING/DTrackWireBased_factory.cc" <<":"<<327<<std::endl;_DBG_std::cerr<<"libraries/TRACKING/DTrackWireBased_factory.cc" <<":"<<327<<" "<<"---- Starting wire based fit with id: "<<mass_hypotheses[j]<<endl;} | ||||||
328 | |||||||
329 | rt->Reset(); | ||||||
330 | rt->q = candidate->charge(); | ||||||
331 | DoFit(i,candidate,rt,loop,ParticleMass(Particle_t(mass_hypotheses[j]))); | ||||||
332 | } | ||||||
333 | |||||||
334 | } | ||||||
335 | } | ||||||
336 | |||||||
337 | // Filter out duplicate tracks | ||||||
338 | FilterDuplicates(); | ||||||
339 | |||||||
340 | // Add any missing hypotheses | ||||||
341 | if (SKIP_MASS_HYPOTHESES_WIRE_BASED==false){ | ||||||
342 | InsertMissingHypotheses(); | ||||||
343 | } | ||||||
344 | |||||||
345 | return NOERROR; | ||||||
346 | } | ||||||
347 | |||||||
348 | |||||||
349 | //------------------ | ||||||
350 | // erun | ||||||
351 | //------------------ | ||||||
352 | jerror_t DTrackWireBased_factory::erun(void) | ||||||
353 | { | ||||||
354 | if (rt) delete rt; | ||||||
355 | return NOERROR; | ||||||
356 | } | ||||||
357 | |||||||
358 | //------------------ | ||||||
359 | // fini | ||||||
360 | //------------------ | ||||||
361 | jerror_t DTrackWireBased_factory::fini(void) | ||||||
362 | { | ||||||
363 | |||||||
364 | return NOERROR; | ||||||
365 | } | ||||||
366 | |||||||
367 | //------------------ | ||||||
368 | // FilterDuplicates | ||||||
369 | //------------------ | ||||||
370 | void DTrackWireBased_factory::FilterDuplicates(void) | ||||||
371 | { | ||||||
372 | /// Look through all current DTrackWireBased objects and remove any | ||||||
373 | /// that have all of their hits in common with another track | ||||||
374 | |||||||
375 | if(_data.size()==0)return; | ||||||
376 | |||||||
377 | if(DEBUG_LEVEL>2)_DBG_std::cerr<<"libraries/TRACKING/DTrackWireBased_factory.cc" <<":"<<377<<" "<<"Looking for clones of wire-based tracks ..."<<endl; | ||||||
378 | |||||||
379 | set<unsigned int> indexes_to_delete; | ||||||
380 | for(unsigned int i=0; i<_data.size()-1; i++){ | ||||||
381 | DTrackWireBased *dtrack1 = _data[i]; | ||||||
382 | |||||||
383 | vector<const DCDCTrackHit*> cdchits1; | ||||||
384 | vector<const DFDCPseudo*> fdchits1; | ||||||
385 | dtrack1->Get(cdchits1); | ||||||
386 | dtrack1->Get(fdchits1); | ||||||
387 | |||||||
388 | JObject::oid_t cand1=dtrack1->candidateid; | ||||||
389 | for(unsigned int j=i+1; j<_data.size(); j++){ | ||||||
390 | DTrackWireBased *dtrack2 = _data[j]; | ||||||
391 | if (dtrack2->candidateid==cand1) continue; | ||||||
392 | if (dtrack2->mass() != dtrack1->mass())continue; | ||||||
393 | |||||||
394 | vector<const DCDCTrackHit*> cdchits2; | ||||||
395 | vector<const DFDCPseudo*> fdchits2; | ||||||
396 | dtrack2->Get(cdchits2); | ||||||
397 | dtrack2->Get(fdchits2); | ||||||
398 | |||||||
399 | // Count number of cdc and fdc hits in common | ||||||
400 | unsigned int Ncdc = count_common_members(cdchits1, cdchits2); | ||||||
401 | unsigned int Nfdc = count_common_members(fdchits1, fdchits2); | ||||||
402 | unsigned int total = Ncdc + Nfdc; | ||||||
403 | |||||||
404 | if (total==0) continue; | ||||||
405 | if(Ncdc!=cdchits1.size() && Ncdc!=cdchits2.size())continue; | ||||||
406 | if(Nfdc!=fdchits1.size() && Nfdc!=fdchits2.size())continue; | ||||||
407 | |||||||
408 | unsigned int total1 = cdchits1.size()+fdchits1.size(); | ||||||
409 | unsigned int total2 = cdchits2.size()+fdchits2.size(); | ||||||
410 | if(total!=total1 && total!=total2)continue; | ||||||
411 | |||||||
412 | if(total1<total2){ | ||||||
413 | // The two track candidates actually correspond to | ||||||
414 | // a single track. Set the candidate id for this | ||||||
415 | // track to the candidate id from the clone match to | ||||||
416 | // prevent multiple clone tracks confusing matters | ||||||
417 | // at a later stage of the reconstruction... | ||||||
418 | _data[j]->candidateid=cand1; | ||||||
419 | indexes_to_delete.insert(i); | ||||||
420 | }else{ | ||||||
421 | indexes_to_delete.insert(j); | ||||||
422 | } | ||||||
423 | |||||||
424 | } | ||||||
425 | } | ||||||
426 | |||||||
427 | if(DEBUG_LEVEL>2)_DBG_std::cerr<<"libraries/TRACKING/DTrackWireBased_factory.cc" <<":"<<427<<" "<<"Found "<<indexes_to_delete.size()<<" wire-based clones"<<endl; | ||||||
428 | |||||||
429 | // Return now if we're keeping everyone | ||||||
430 | if(indexes_to_delete.size()==0)return; | ||||||
431 | |||||||
432 | // Copy pointers that we want to keep to a new container and delete | ||||||
433 | // the clone objects | ||||||
434 | vector<DTrackWireBased*> new_data; | ||||||
435 | for(unsigned int i=0; i<_data.size(); i++){ | ||||||
436 | if(indexes_to_delete.find(i)==indexes_to_delete.end()){ | ||||||
437 | new_data.push_back(_data[i]); | ||||||
438 | }else{ | ||||||
439 | delete _data[i]; | ||||||
440 | if(DEBUG_LEVEL>1)_DBG_std::cerr<<"libraries/TRACKING/DTrackWireBased_factory.cc" <<":"<<440<<" "<<"Deleting clone wire-based track "<<i<<endl; | ||||||
441 | } | ||||||
442 | } | ||||||
443 | _data = new_data; | ||||||
444 | } | ||||||
445 | |||||||
446 | // Routine to find the hits, do the fit, and fill the list of wire-based tracks | ||||||
447 | void DTrackWireBased_factory::DoFit(unsigned int c_id, | ||||||
448 | const DTrackCandidate *candidate, | ||||||
449 | DReferenceTrajectory *rt, | ||||||
450 | JEventLoop *loop, double mass){ | ||||||
451 | // Get the hits from the candidate | ||||||
452 | vector<const DFDCPseudo*>myfdchits; | ||||||
453 | candidate->GetT(myfdchits); | ||||||
454 | vector<const DCDCTrackHit *>mycdchits; | ||||||
455 | candidate->GetT(mycdchits); | ||||||
456 | |||||||
457 | // Do the fit | ||||||
458 | DTrackFitter::fit_status_t status = DTrackFitter::kFitNotDone; | ||||||
459 | if (USE_HITS_FROM_CANDIDATE) { | ||||||
460 | fitter->Reset(); | ||||||
461 | fitter->SetFitType(DTrackFitter::kWireBased); | ||||||
462 | |||||||
463 | fitter->AddHits(myfdchits); | ||||||
464 | fitter->AddHits(mycdchits); | ||||||
465 | |||||||
466 | status=fitter->FitTrack(candidate->position(),candidate->momentum(), | ||||||
467 | candidate->charge(),mass,0.); | ||||||
468 | } | ||||||
469 | else{ | ||||||
470 | fitter->Reset(); | ||||||
471 | fitter->SetFitType(DTrackFitter::kWireBased); | ||||||
472 | // Swim a reference trajectory using the candidate starting momentum | ||||||
473 | // and position | ||||||
474 | rt->SetMass(mass); | ||||||
475 | //rt->Swim(candidate->position(),candidate->momentum(),candidate->charge()); | ||||||
476 | rt->FastSwimForHitSelection(candidate->position(),candidate->momentum(),candidate->charge()); | ||||||
477 | |||||||
478 | status=fitter->FindHitsAndFitTrack(*candidate,rt,loop,mass, | ||||||
479 | mycdchits.size()+2*myfdchits.size()); | ||||||
480 | if (/*false && */status==DTrackFitter::kFitNotDone){ | ||||||
481 | if (DEBUG_LEVEL>1)_DBG_std::cerr<<"libraries/TRACKING/DTrackWireBased_factory.cc" <<":"<<481<<" " << "Using hits from candidate..." << endl; | ||||||
482 | fitter->Reset(); | ||||||
483 | |||||||
484 | fitter->AddHits(myfdchits); | ||||||
485 | fitter->AddHits(mycdchits); | ||||||
486 | |||||||
487 | status=fitter->FitTrack(candidate->position(),candidate->momentum(), | ||||||
488 | candidate->charge(),mass,0.); | ||||||
489 | } | ||||||
490 | } | ||||||
491 | |||||||
492 | // if the fit returns chisq=-1, something went terribly wrong... | ||||||
493 | if (fitter->GetChisq()<0){ | ||||||
494 | status=DTrackFitter::kFitFailed; | ||||||
495 | } | ||||||
496 | |||||||
497 | // Check the status of the fit | ||||||
498 | switch(status){ | ||||||
499 | case DTrackFitter::kFitNotDone: | ||||||
500 | //_DBG_<<"Fitter returned kFitNotDone. This should never happen!!"<<endl; | ||||||
501 | case DTrackFitter::kFitFailed: | ||||||
502 | break; | ||||||
503 | case DTrackFitter::kFitNoImprovement: | ||||||
504 | case DTrackFitter::kFitSuccess: | ||||||
505 | if(!isfinite(fitter->GetFitParameters().position().X())) break; | ||||||
506 | { | ||||||
507 | // Make a new wire-based track | ||||||
508 | DTrackWireBased *track = new DTrackWireBased(); | ||||||
509 | *static_cast<DTrackingData*>(track) = fitter->GetFitParameters(); | ||||||
510 | |||||||
511 | track->chisq = fitter->GetChisq(); | ||||||
512 | track->Ndof = fitter->GetNdof(); | ||||||
513 | track->FOM = TMath::Prob(track->chisq, track->Ndof); | ||||||
514 | track->pulls =std::move(fitter->GetPulls()); | ||||||
515 | track->extrapolations=std::move(fitter->GetExtrapolations()); | ||||||
516 | track->candidateid = c_id+1; | ||||||
517 | |||||||
518 | // Add hits used as associated objects | ||||||
519 | vector<const DCDCTrackHit*> cdchits = fitter->GetCDCFitHits(); | ||||||
520 | vector<const DFDCPseudo*> fdchits = fitter->GetFDCFitHits(); | ||||||
521 | sort(cdchits.begin(), cdchits.end(), CDCSortByRincreasing); | ||||||
522 | sort(fdchits.begin(), fdchits.end(), FDCSortByZincreasing); | ||||||
523 | for(unsigned int m=0; m<cdchits.size(); m++)track->AddAssociatedObject(cdchits[m]); | ||||||
524 | for(unsigned int m=0; m<fdchits.size(); m++)track->AddAssociatedObject(fdchits[m]); | ||||||
525 | |||||||
526 | // Set CDC ring & FDC plane hit patterns before candidate tracks are associated | ||||||
527 | vector<const DCDCTrackHit*> tempCDCTrackHits; | ||||||
528 | vector<const DFDCPseudo*> tempFDCPseudos; | ||||||
529 | track->Get(tempCDCTrackHits); | ||||||
530 | track->Get(tempFDCPseudos); | ||||||
531 | track->dCDCRings = dPIDAlgorithm->Get_CDCRingBitPattern(tempCDCTrackHits); | ||||||
532 | track->dFDCPlanes = dPIDAlgorithm->Get_FDCPlaneBitPattern(tempFDCPseudos); | ||||||
533 | |||||||
534 | // Add DTrackCandidate as associated object | ||||||
535 | track->AddAssociatedObject(candidate); | ||||||
536 | |||||||
537 | _data.push_back(track); | ||||||
538 | break; | ||||||
539 | } | ||||||
540 | default: | ||||||
541 | break; | ||||||
542 | } | ||||||
543 | } | ||||||
544 | |||||||
545 | // If the fit failed for certain hypotheses, fill in the gaps using data from | ||||||
546 | // successful fits for each candidate. | ||||||
547 | bool DTrackWireBased_factory::InsertMissingHypotheses(void){ | ||||||
548 | if (_data.size()==0) return false; | ||||||
549 | |||||||
550 | // Make sure the tracks are ordered by candidate id | ||||||
551 | sort(_data.begin(),_data.end(),DTrackWireBased_cmp); | ||||||
552 | |||||||
553 | JObject::oid_t old_id=_data[0]->candidateid; | ||||||
554 | unsigned int mass_bits=0; | ||||||
555 | double q=_data[0]->charge(); | ||||||
556 | vector<DTrackWireBased*>myhypotheses; | ||||||
557 | vector<DTrackWireBased*>tracks_to_add; | ||||||
558 | for (size_t i=0;i<_data.size();i++){ | ||||||
559 | if (_data[i]->candidateid!=old_id){ | ||||||
560 | int num_hyp=myhypotheses.size(); | ||||||
561 | if ((q<0 && num_hyp!=mNumHypMinus)||(q>0 && num_hyp!=mNumHypPlus)){ | ||||||
562 | AddMissingTrackHypotheses(mass_bits,tracks_to_add,myhypotheses,q); | ||||||
563 | } | ||||||
564 | |||||||
565 | // Clear the myhypotheses vector for the next track | ||||||
566 | myhypotheses.clear(); | ||||||
567 | // Reset charge | ||||||
568 | q=_data[i]->charge(); | ||||||
569 | |||||||
570 | // Set the bit for this mass hypothesis | ||||||
571 | mass_bits = 1<<_data[i]->PID(); | ||||||
572 | |||||||
573 | // Add the data to the myhypotheses vector | ||||||
574 | myhypotheses.push_back(_data[i]); | ||||||
575 | } | ||||||
576 | else{ | ||||||
577 | myhypotheses.push_back(_data[i]); | ||||||
578 | |||||||
579 | // Set the bit for this mass hypothesis | ||||||
580 | mass_bits |= 1<< _data[i]->PID(); | ||||||
581 | } | ||||||
582 | |||||||
583 | old_id=_data[i]->candidateid; | ||||||
584 | } | ||||||
585 | // Deal with last track candidate | ||||||
586 | int num_hyp=myhypotheses.size(); | ||||||
587 | if ((q<0 && num_hyp!=mNumHypMinus)||(q>0 && num_hyp!=mNumHypPlus)){ | ||||||
588 | AddMissingTrackHypotheses(mass_bits,tracks_to_add,myhypotheses,q); | ||||||
589 | } | ||||||
590 | |||||||
591 | // Add the new list of tracks to the output list | ||||||
592 | if (tracks_to_add.size()>0){ | ||||||
593 | for (size_t i=0;i<tracks_to_add.size();i++){ | ||||||
594 | _data.push_back(tracks_to_add[i]); | ||||||
595 | } | ||||||
596 | // Make sure the tracks are ordered by candidate id | ||||||
597 | sort(_data.begin(),_data.end(),DTrackWireBased_cmp); | ||||||
598 | } | ||||||
599 | |||||||
600 | return true; | ||||||
601 | } | ||||||
602 | |||||||
603 | // Create a track with a mass hypothesis that was not present in the list of | ||||||
604 | // fitted tracks from an existing fitted track. | ||||||
605 | void DTrackWireBased_factory::AddMissingTrackHypothesis(vector<DTrackWireBased*>&tracks_to_add, | ||||||
606 | const DTrackWireBased *src_track, | ||||||
607 | double my_mass, | ||||||
608 | double q){ | ||||||
609 | // Create a new wire-based track object | ||||||
610 | DTrackWireBased *wirebased_track = new DTrackWireBased(); | ||||||
611 | *static_cast<DTrackingData*>(wirebased_track) = *static_cast<const DTrackingData*>(src_track); | ||||||
612 | |||||||
613 | // Copy over DKinematicData part from the result of a successful fit | ||||||
614 | wirebased_track->setPID(IDTrack(q, my_mass)); | ||||||
615 | wirebased_track->chisq = src_track->chisq; | ||||||
616 | wirebased_track->Ndof = src_track->Ndof; | ||||||
617 | wirebased_track->pulls = src_track->pulls; | ||||||
618 | wirebased_track->extrapolations = src_track->extrapolations; | ||||||
619 | wirebased_track->candidateid=src_track->candidateid; | ||||||
620 | wirebased_track->FOM=src_track->FOM; | ||||||
621 | wirebased_track->IsSmoothed=src_track->IsSmoothed; | ||||||
622 | wirebased_track->dCDCRings=src_track->dCDCRings; | ||||||
623 | wirebased_track->dFDCPlanes=src_track->dFDCPlanes; | ||||||
624 | |||||||
625 | // (Partially) compensate for the difference in energy loss between the | ||||||
626 | // source track and a particle of mass my_mass | ||||||
627 | DVector3 position,momentum; | ||||||
628 | if (wirebased_track->extrapolations.at(SYS_CDC).size()>0){ | ||||||
629 | unsigned int index=wirebased_track->extrapolations.at(SYS_CDC).size()-1; | ||||||
630 | position=wirebased_track->extrapolations[SYS_CDC][index].position; | ||||||
631 | momentum=wirebased_track->extrapolations[SYS_CDC][index].momentum; | ||||||
632 | } | ||||||
633 | else if (wirebased_track->extrapolations.at(SYS_FDC).size()>0){ | ||||||
634 | unsigned int index=wirebased_track->extrapolations.at(SYS_FDC).size()-1; | ||||||
635 | position=wirebased_track->extrapolations[SYS_FDC][index].position; | ||||||
636 | momentum=wirebased_track->extrapolations[SYS_FDC][index].momentum; | ||||||
637 | } | ||||||
638 | if (momentum.Mag()>0.){ | ||||||
639 | CorrectForELoss(position,momentum,q,my_mass); | ||||||
640 | |||||||
641 | wirebased_track->setMomentum(momentum); | ||||||
642 | wirebased_track->setPosition(position); | ||||||
643 | } | ||||||
644 | |||||||
645 | // Get the hits used in the fit and add them as associated objects | ||||||
646 | vector<const DCDCTrackHit *>cdchits; | ||||||
647 | src_track->GetT(cdchits); | ||||||
648 | vector<const DFDCPseudo *>fdchits; | ||||||
649 | src_track->GetT(fdchits); | ||||||
650 | for(unsigned int m=0; m<fdchits.size(); m++) | ||||||
651 | wirebased_track->AddAssociatedObject(fdchits[m]); | ||||||
652 | for(unsigned int m=0; m<cdchits.size(); m++) | ||||||
653 | wirebased_track->AddAssociatedObject(cdchits[m]); | ||||||
654 | |||||||
655 | tracks_to_add.push_back(wirebased_track); | ||||||
656 | } | ||||||
657 | |||||||
658 | // Use the FastSwim method in DReferenceTrajectory to propagate back to the | ||||||
659 | // POCA to the beam line, adding a bit of energy at each step that would have | ||||||
660 | // been lost had the particle emerged from the target. | ||||||
661 | void DTrackWireBased_factory::CorrectForELoss(DVector3 &position,DVector3 &momentum,double q,double my_mass){ | ||||||
662 | rt->Reset(); | ||||||
663 | rt->q = q; | ||||||
664 | rt->SetMass(my_mass); | ||||||
665 | rt->SetPLossDirection(DReferenceTrajectory::kBackward); | ||||||
666 | DVector3 last_pos,last_mom; | ||||||
667 | DVector3 origin(0.,0.,65.); | ||||||
668 | DVector3 dir(0.,0.,1.); | ||||||
669 | rt->FastSwim(position,momentum,last_pos,last_mom,rt->q,origin,dir,300.); | ||||||
670 | position=last_pos; | ||||||
671 | momentum=last_mom; | ||||||
672 | } | ||||||
673 | |||||||
674 | |||||||
675 | // Fill in all missing hypotheses for a given track candidate | ||||||
676 | void DTrackWireBased_factory::AddMissingTrackHypotheses(unsigned int mass_bits, | ||||||
677 | vector<DTrackWireBased*>&tracks_to_add, | ||||||
678 | vector<DTrackWireBased *>&myhypotheses, | ||||||
679 | double q){ | ||||||
680 | Particle_t negative_particles[3]={KMinus,PiMinus,Electron}; | ||||||
681 | Particle_t positive_particles[3]={KPlus,PiPlus,Positron}; | ||||||
682 | |||||||
683 | unsigned int last_index=myhypotheses.size()-1; | ||||||
684 | if (q>0){ | ||||||
685 | if ((mass_bits & (1<<Proton))==0){ | ||||||
686 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index], | ||||||
687 | ParticleMass(Proton),+1.); | ||||||
688 | } | ||||||
689 | for (int i=0;i<3;i++){ | ||||||
690 | if ((mass_bits & (1<<positive_particles[i]))==0){ | ||||||
691 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[0], | ||||||
692 | ParticleMass(positive_particles[i]),+1.); | ||||||
693 | } | ||||||
694 | } | ||||||
695 | } | ||||||
696 | else{ | ||||||
697 | if ((mass_bits & (1<<AntiProton))==0){ | ||||||
698 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index], | ||||||
699 | ParticleMass(Proton),-1.); | ||||||
700 | } | ||||||
701 | for (int i=0;i<3;i++){ | ||||||
702 | if ((mass_bits & (1<<negative_particles[i]))==0){ | ||||||
703 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[0], | ||||||
704 | ParticleMass(negative_particles[i]),-1.); | ||||||
705 | } | ||||||
706 | } | ||||||
707 | } | ||||||
708 | } |
1 | // $Id: JEventLoop.h 1763 2006-05-10 14:29:25Z davidl $ | ||||||
2 | // | ||||||
3 | // File: JEventLoop.h | ||||||
4 | // Created: Wed Jun 8 12:30:51 EDT 2005 | ||||||
5 | // Creator: davidl (on Darwin wire129.jlab.org 7.8.0 powerpc) | ||||||
6 | // | ||||||
7 | |||||||
8 | #ifndef _JEventLoop_ | ||||||
9 | #define _JEventLoop_ | ||||||
10 | |||||||
11 | #include <sys/time.h> | ||||||
12 | |||||||
13 | #include <vector> | ||||||
14 | #include <list> | ||||||
15 | #include <string> | ||||||
16 | #include <utility> | ||||||
17 | #include <typeinfo> | ||||||
18 | #include <string.h> | ||||||
19 | #include <map> | ||||||
20 | #include <utility> | ||||||
21 | using std::vector; | ||||||
22 | using std::list; | ||||||
23 | using std::string; | ||||||
24 | using std::type_info; | ||||||
25 | |||||||
26 | #include <JANA/jerror.h> | ||||||
27 | #include <JANA/JObject.h> | ||||||
28 | #include <JANA/JException.h> | ||||||
29 | #include <JANA/JEvent.h> | ||||||
30 | #include <JANA/JThread.h> | ||||||
31 | #include <JANA/JFactory_base.h> | ||||||
32 | #include <JANA/JCalibration.h> | ||||||
33 | #include <JANA/JGeometry.h> | ||||||
34 | #include <JANA/JResourceManager.h> | ||||||
35 | #include <JANA/JStreamLog.h> | ||||||
36 | |||||||
37 | // The following is here just so we can use ROOT's THtml class to generate documentation. | ||||||
38 | #include "cint.h" | ||||||
39 | |||||||
40 | |||||||
41 | // Place everything in JANA namespace | ||||||
42 | namespace jana{ | ||||||
43 | |||||||
44 | |||||||
45 | template<class T> class JFactory; | ||||||
46 | class JApplication; | ||||||
47 | class JEventProcessor; | ||||||
48 | |||||||
49 | |||||||
50 | class JEventLoop{ | ||||||
51 | public: | ||||||
52 | |||||||
53 | friend class JApplication; | ||||||
54 | |||||||
55 | enum data_source_t{ | ||||||
56 | DATA_NOT_AVAILABLE = 1, | ||||||
57 | DATA_FROM_CACHE, | ||||||
58 | DATA_FROM_SOURCE, | ||||||
59 | DATA_FROM_FACTORY | ||||||
60 | }; | ||||||
61 | |||||||
62 | typedef struct{ | ||||||
63 | string caller_name; | ||||||
64 | string caller_tag; | ||||||
65 | string callee_name; | ||||||
66 | string callee_tag; | ||||||
67 | double start_time; | ||||||
68 | double end_time; | ||||||
69 | data_source_t data_source; | ||||||
70 | }call_stack_t; | ||||||
71 | |||||||
72 | typedef struct{ | ||||||
73 | const char* factory_name; | ||||||
74 | string tag; | ||||||
75 | const char* filename; | ||||||
76 | int line; | ||||||
77 | }error_call_stack_t; | ||||||
78 | |||||||
79 | JEventLoop(JApplication *app); ///< Constructor | ||||||
80 | virtual ~JEventLoop(); ////< Destructor | ||||||
81 | virtual const char* className(void){return static_className();} | ||||||
82 | static const char* static_className(void){return "JEventLoop";} | ||||||
83 | |||||||
84 | JApplication* GetJApplication(void) const {return app;} ///< Get pointer to the JApplication object | ||||||
85 | void RefreshProcessorListFromJApplication(void); ///< Re-copy the list of JEventProcessors from JApplication | ||||||
86 | virtual jerror_t AddFactory(JFactory_base* factory); ///< Add a factory | ||||||
87 | jerror_t RemoveFactory(JFactory_base* factory); ///< Remove a factory | ||||||
88 | JFactory_base* GetFactory(const string data_name, const char *tag="", bool allow_deftag=true); ///< Get a specific factory pointer | ||||||
89 | vector<JFactory_base*> GetFactories(void) const {return factories;} ///< Get all factory pointers | ||||||
90 | void GetFactoryNames(vector<string> &factorynames); ///< Get names of all factories in name:tag format | ||||||
91 | void GetFactoryNames(map<string,string> &factorynames); ///< Get names of all factories in map with key=name, value=tag | ||||||
92 | map<string,string> GetDefaultTags(void) const {return default_tags;} | ||||||
93 | jerror_t ClearFactories(void); ///< Reset all factories in preparation for next event. | ||||||
94 | jerror_t PrintFactories(int sparsify=0); ///< Print a list of all factories. | ||||||
95 | jerror_t Print(const string data_name, const char *tag=""); ///< Print the data of the given type | ||||||
96 | |||||||
97 | JCalibration* GetJCalibration(); | ||||||
98 | template<class T> bool GetCalib(string namepath, map<string,T> &vals); | ||||||
99 | template<class T> bool GetCalib(string namepath, vector<T> &vals); | ||||||
100 | template<class T> bool GetCalib(string namepath, T &val); | ||||||
101 | |||||||
102 | JGeometry* GetJGeometry(); | ||||||
103 | template<class T> bool GetGeom(string namepath, map<string,T> &vals); | ||||||
104 | template<class T> bool GetGeom(string namepath, T &val); | ||||||
105 | |||||||
106 | JResourceManager* GetJResourceManager(void); | ||||||
107 | string GetResource(string namepath); | ||||||
108 | template<class T> bool GetResource(string namepath, T vals, int event_number=0); | ||||||
109 | |||||||
110 | void Initialize(void); ///< Do initializations just before event processing starts | ||||||
111 | jerror_t Loop(void); ///< Loop over events | ||||||
112 | jerror_t OneEvent(uint64_t event_number); ///< Process a specific single event (if source supports it) | ||||||
113 | jerror_t OneEvent(void); ///< Process a single event | ||||||
114 | inline void Pause(void){pause = 1;} ///< Pause event processing | ||||||
115 | inline void Resume(void){pause = 0;} ///< Resume event processing | ||||||
116 | inline void Quit(void){quit = 1;} ///< Clean up and exit the event loop | ||||||
117 | inline bool GetQuit(void) const {return quit;} | ||||||
118 | void QuitProgram(void); | ||||||
119 | |||||||
120 | // Support for random access of events | ||||||
121 | bool HasRandomAccess(void); | ||||||
122 | void AddToEventQueue(uint64_t event_number){ next_events_to_process.push_back(event_number); } | ||||||
123 | void AddToEventQueue(list<uint64_t> &event_numbers) { next_events_to_process.insert(next_events_to_process.end(), event_numbers.begin(), event_numbers.end()); } | ||||||
124 | list<uint64_t> GetEventQueue(void){ return next_events_to_process; } | ||||||
125 | void ClearEventQueue(void){ next_events_to_process.clear(); } | ||||||
126 | |||||||
127 | template<class T> JFactory<T>* GetSingle(const T* &t, const char *tag="", bool exception_if_not_one=true); ///< Get pointer to first data object from (source or factory). | ||||||
128 | template<class T> JFactory<T>* Get(vector<const T*> &t, const char *tag="", bool allow_deftag=true); ///< Get data object pointers from (source or factory) | ||||||
129 | template<class T> JFactory<T>* GetFromFactory(vector<const T*> &t, const char *tag="", data_source_t &data_source=null_data_source, bool allow_deftag=true); ///< Get data object pointers from factory | ||||||
130 | template<class T> jerror_t GetFromSource(vector<const T*> &t, JFactory_base *factory=NULL__null); ///< Get data object pointers from source. | ||||||
131 | inline JEvent& GetJEvent(void){return event;} ///< Get pointer to the current JEvent object. | ||||||
132 | inline void SetJEvent(JEvent *event){this->event = *event;} ///< Set the JEvent pointer. | ||||||
133 | inline void SetAutoFree(int auto_free){this->auto_free = auto_free;} ///< Set the Auto-Free flag on/off | ||||||
134 | inline pthread_t GetPThreadID(void) const {return pthread_id;} ///< Get the pthread of the thread to which this JEventLoop belongs | ||||||
135 | double GetInstantaneousRate(void) const {return rate_instantaneous;} ///< Get the current event processing rate | ||||||
136 | double GetIntegratedRate(void) const {return rate_integrated;} ///< Get the current event processing rate | ||||||
137 | double GetLastEventProcessingTime(void) const {return delta_time_single;} | ||||||
138 | unsigned int GetNevents(void) const {return Nevents;} | ||||||
139 | |||||||
140 | inline bool CheckEventBoundary(uint64_t event_numberA, uint64_t event_numberB); | ||||||
141 | |||||||
142 | inline bool GetCallStackRecordingStatus(void){ return record_call_stack; } | ||||||
143 | inline void DisableCallStackRecording(void){ record_call_stack = false; } | ||||||
144 | inline void EnableCallStackRecording(void){ record_call_stack = true; } | ||||||
145 | inline void CallStackStart(JEventLoop::call_stack_t &cs, const string &caller_name, const string &caller_tag, const string callee_name, const string callee_tag); | ||||||
146 | inline void CallStackEnd(JEventLoop::call_stack_t &cs); | ||||||
147 | inline vector<call_stack_t> GetCallStack(void){return call_stack;} ///< Get the current factory call stack | ||||||
148 | inline void AddToCallStack(call_stack_t &cs){if(record_call_stack) call_stack.push_back(cs);} ///< Add specified item to call stack record but only if record_call_stack is true | ||||||
149 | inline void AddToErrorCallStack(error_call_stack_t &cs){error_call_stack.push_back(cs);} ///< Add layer to the factory call stack | ||||||
150 | inline vector<error_call_stack_t> GetErrorCallStack(void){return error_call_stack;} ///< Get the current factory error call stack | ||||||
151 | void PrintErrorCallStack(void); ///< Print the current factory call stack | ||||||
152 | |||||||
153 | const JObject* FindByID(JObject::oid_t id); ///< Find a data object by its identifier. | ||||||
154 | template<class T> const T* FindByID(JObject::oid_t id); ///< Find a data object by its type and identifier | ||||||
155 | JFactory_base* FindOwner(const JObject *t); ///< Find the factory that owns a data object by pointer | ||||||
156 | JFactory_base* FindOwner(JObject::oid_t id); ///< Find a factory that owns a data object by identifier | ||||||
157 | |||||||
158 | // User defined references | ||||||
159 | template<class T> void SetRef(T *t); ///< Add a user reference to this JEventLoop (must be a pointer) | ||||||
160 | template<class T> T* GetRef(void); ///< Get a user-defined reference of a specific type | ||||||
161 | template<class T> vector<T*> GetRefsT(void); ///< Get all user-defined refrences of a specicif type | ||||||
162 | vector<pair<const char*, void*> > GetRefs(void){ return user_refs; } ///< Get copy of full list of user-defined references | ||||||
163 | template<class T> void RemoveRef(T *t); ///< Remove user reference from list | ||||||
164 | |||||||
165 | // Convenience methods wrapping JEvent methods of same name | ||||||
166 | uint64_t GetStatus(void){return event.GetStatus();} | ||||||
167 | bool GetStatusBit(uint32_t bit){return event.GetStatusBit(bit);} | ||||||
168 | bool SetStatusBit(uint32_t bit, bool val=true){return event.SetStatusBit(bit, val);} | ||||||
169 | bool ClearStatusBit(uint32_t bit){return event.ClearStatusBit(bit);} | ||||||
170 | void ClearStatus(void){event.ClearStatus();} | ||||||
171 | void SetStatusBitDescription(uint32_t bit, string description){event.SetStatusBitDescription(bit, description);} | ||||||
172 | string GetStatusBitDescription(uint32_t bit){return event.GetStatusBitDescription(bit);} | ||||||
173 | void GetStatusBitDescriptions(map<uint32_t, string> &status_bit_descriptions){return event.GetStatusBitDescriptions(status_bit_descriptions);} | ||||||
174 | string StatusWordToString(void); | ||||||
175 | |||||||
176 | private: | ||||||
177 | JEvent event; | ||||||
178 | vector<JFactory_base*> factories; | ||||||
179 | vector<JEventProcessor*> processors; | ||||||
180 | vector<error_call_stack_t> error_call_stack; | ||||||
181 | vector<call_stack_t> call_stack; | ||||||
182 | JApplication *app; | ||||||
183 | JThread *jthread; | ||||||
184 | bool initialized; | ||||||
185 | bool print_parameters_called; | ||||||
186 | int pause; | ||||||
187 | int quit; | ||||||
188 | int auto_free; | ||||||
189 | pthread_t pthread_id; | ||||||
190 | map<string, string> default_tags; | ||||||
191 | vector<pair<string,string> > auto_activated_factories; | ||||||
192 | bool record_call_stack; | ||||||
193 | string caller_name; | ||||||
194 | string caller_tag; | ||||||
195 | vector<uint64_t> event_boundaries; | ||||||
196 | int32_t event_boundaries_run; ///< Run number boundaries were retrieved from (possbily 0) | ||||||
197 | list<uint64_t> next_events_to_process; | ||||||
198 | |||||||
199 | uint64_t Nevents; ///< Total events processed (this thread) | ||||||
200 | uint64_t Nevents_rate; ///< Num. events accumulated for "instantaneous" rate | ||||||
201 | double delta_time_single; ///< Time spent processing last event | ||||||
202 | double delta_time_rate; ///< Integrated time accumulated "instantaneous" rate (partial number of events) | ||||||
203 | double delta_time; ///< Total time spent processing events (this thread) | ||||||
204 | double rate_instantaneous; ///< Latest instantaneous rate | ||||||
205 | double rate_integrated; ///< Rate integrated over all events | ||||||
206 | |||||||
207 | static data_source_t null_data_source; | ||||||
208 | |||||||
209 | vector<pair<const char*, void*> > user_refs; | ||||||
210 | }; | ||||||
211 | |||||||
212 | |||||||
213 | // The following is here just so we can use ROOT's THtml class to generate documentation. | ||||||
214 | #ifdef G__DICTIONARY | ||||||
215 | typedef JEventLoop::call_stack_t call_stack_t; | ||||||
216 | typedef JEventLoop::error_call_stack_t error_call_stack_t; | ||||||
217 | #endif | ||||||
218 | |||||||
219 | #if !defined(__CINT__) && !defined(__CLING__) | ||||||
220 | |||||||
221 | //------------- | ||||||
222 | // GetSingle | ||||||
223 | //------------- | ||||||
224 | template<class T> | ||||||
225 | JFactory<T>* JEventLoop::GetSingle(const T* &t, const char *tag, bool exception_if_not_one) | ||||||
226 | { | ||||||
227 | /// This is a convenience method that can be used to get a pointer to the single | ||||||
228 | /// object of type T from the specified factory. It simply calls the Get(vector<...>) method | ||||||
229 | /// and copies the first pointer into "t" (or NULL if something other than 1 object is returned). | ||||||
230 | /// | ||||||
231 | /// This is intended to address the common situation in which there is an interest | ||||||
232 | /// in the event if and only if there is exactly 1 object of type T. If the event | ||||||
233 | /// has no objects of that type or more than 1 object of that type (for the specified | ||||||
234 | /// factory) then an exception of type "unsigned long" is thrown with the value | ||||||
235 | /// being the number of objects of type T. You can supress the exception by setting | ||||||
236 | /// exception_if_not_one to false. In that case, you will have to check if t==NULL to | ||||||
237 | /// know if the call succeeded. | ||||||
238 | vector<const T*> v; | ||||||
239 | JFactory<T> *fac = Get(v, tag); | ||||||
240 | |||||||
241 | if(v.size()!=1){ | ||||||
242 | t = NULL__null; | ||||||
243 | if(exception_if_not_one) throw v.size(); | ||||||
244 | } | ||||||
245 | |||||||
246 | t = v[0]; | ||||||
247 | |||||||
248 | return fac; | ||||||
249 | } | ||||||
250 | |||||||
251 | //------------- | ||||||
252 | // Get | ||||||
253 | //------------- | ||||||
254 | template<class T> | ||||||
255 | JFactory<T>* JEventLoop::Get(vector<const T*> &t, const char *tag, bool allow_deftag) | ||||||
256 | { | ||||||
257 | /// Retrieve or generate the array of objects of | ||||||
258 | /// type T for the curent event being processed | ||||||
259 | /// by this thread. | ||||||
260 | /// | ||||||
261 | /// By default, preference is given to reading the | ||||||
262 | /// objects from the data source(e.g. file) before generating | ||||||
263 | /// them in the factory. A flag exists in the factory | ||||||
264 | /// however to change this so that the factory is | ||||||
265 | /// given preference. | ||||||
266 | /// | ||||||
267 | /// Note that regardless of the setting of this flag, | ||||||
268 | /// the data are only either read in or generated once. | ||||||
269 | /// Ownership of the objects will always be with the | ||||||
270 | /// factory so subsequent calls will always return pointers to | ||||||
271 | /// the same data. | ||||||
272 | /// | ||||||
273 | /// If the factory is called on to generate the data, | ||||||
274 | /// it is done by calling the factory's Get() method | ||||||
275 | /// which, in turn, calls the evnt() method. | ||||||
276 | /// | ||||||
277 | /// First, we just call the GetFromFactory() method. | ||||||
278 | /// It will make the initial decision as to whether | ||||||
279 | /// it should look in the source first or not. If | ||||||
280 | /// it returns NULL, then the factory couldn't be | ||||||
281 | /// found so we automatically try the file. | ||||||
282 | /// | ||||||
283 | /// Note that if no factory exists to hold the objects | ||||||
284 | /// from the file, one can be created automatically | ||||||
285 | /// providing the <i>JANA:AUTOFACTORYCREATE</i> | ||||||
286 | /// configuration parameter is set. | ||||||
287 | |||||||
288 | // Check if a tag was specified for this data type to use for the | ||||||
289 | // default. | ||||||
290 | const char *mytag = tag
| ||||||
291 | if(strlen(mytag)==0 && allow_deftag
| ||||||
292 | map<string, string>::const_iterator iter = default_tags.find(T::static_className()); | ||||||
293 | if(iter!=default_tags.end())tag = iter->second.c_str(); | ||||||
294 | } | ||||||
295 | |||||||
296 | |||||||
297 | // If we are trying to keep track of the call stack then we | ||||||
298 | // need to add a new call_stack_t object to the the list | ||||||
299 | // and initialize it with the start time and caller/callee | ||||||
300 | // info. | ||||||
301 | call_stack_t cs; | ||||||
302 | |||||||
303 | // Optionally record starting info of call stack entry | ||||||
304 | if(record_call_stack) CallStackStart(cs, caller_name, caller_tag, T::static_className(), tag); | ||||||
305 | |||||||
306 | // Get the data (or at least try to) | ||||||
307 | JFactory<T>* factory=NULL__null; | ||||||
308 | try{ | ||||||
309 | factory = GetFromFactory(t, tag, cs.data_source, allow_deftag); | ||||||
310 | if(!factory){ | ||||||
311 | // No factory exists for this type and tag. It's possible | ||||||
312 | // that the source may be able to provide the objects | ||||||
313 | // but it will need a place to put them. We can create a | ||||||
314 | // dumb JFactory just to hold the data in case the source | ||||||
315 | // can provide the objects. Before we do though, make sure | ||||||
316 | // the user condones this via the presence of the | ||||||
317 | // "JANA:AUTOFACTORYCREATE" config parameter. | ||||||
318 | string p; | ||||||
319 | try{ | ||||||
320 | gPARMS->GetParameter("JANA:AUTOFACTORYCREATE", p); | ||||||
321 | }catch(...){} | ||||||
322 | if(p.size()==0){ | ||||||
323 | jout<<std::endl; | ||||||
324 | _DBG__std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<324<<std::endl; | ||||||
325 | jout<<"No factory of type \""<<T::static_className()<<"\" with tag \""<<tag<<"\" exists."<<std::endl; | ||||||
326 | jout<<"If you are reading objects from a file, I can auto-create a factory"<<std::endl; | ||||||
327 | jout<<"of the appropriate type to hold the objects, but this feature is turned"<<std::endl; | ||||||
328 | jout<<"off by default. To turn it on, set the \"JANA:AUTOFACTORYCREATE\""<<std::endl; | ||||||
329 | jout<<"configuration parameter. This can usually be done by passing the"<<std::endl; | ||||||
330 | jout<<"following argument to the program from the command line:"<<std::endl; | ||||||
331 | jout<<std::endl; | ||||||
332 | jout<<" -PJANA:AUTOFACTORYCREATE=1"<<std::endl; | ||||||
333 | jout<<std::endl; | ||||||
334 | jout<<"Note that since the most commonly expected occurance of this situation."<<std::endl; | ||||||
335 | jout<<"is an error, the program will now throw an exception so that the factory."<<std::endl; | ||||||
336 | jout<<"call stack can be printed."<<std::endl; | ||||||
337 | jout<<std::endl; | ||||||
338 | throw exception(); | ||||||
339 | }else{ | ||||||
340 | AddFactory(new JFactory<T>(tag)); | ||||||
341 | jout<<__FILE__"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"<<":"<<__LINE__341<<" Auto-created "<<T::static_className()<<":"<<tag<<" factory"<<std::endl; | ||||||
342 | |||||||
343 | // Now try once more. The GetFromFactory method will call | ||||||
344 | // GetFromSource since it's empty. | ||||||
345 | factory = GetFromFactory(t, tag, cs.data_source, allow_deftag); | ||||||
346 | } | ||||||
347 | } | ||||||
348 | }catch(exception &e){ | ||||||
349 | // Uh-oh, an exception was thrown. Add us to the call stack | ||||||
350 | // and re-throw the exception | ||||||
351 | error_call_stack_t ecs; | ||||||
352 | ecs.factory_name = T::static_className(); | ||||||
353 | ecs.tag = tag; | ||||||
354 | ecs.filename = NULL__null; | ||||||
355 | error_call_stack.push_back(ecs); | ||||||
356 | throw e; | ||||||
357 | } | ||||||
358 | |||||||
359 | // If recording the call stack, update the end_time field and add to stack | ||||||
360 | if(record_call_stack) CallStackEnd(cs); | ||||||
361 | |||||||
362 | return factory; | ||||||
363 | } | ||||||
364 | |||||||
365 | //------------- | ||||||
366 | // GetFromFactory | ||||||
367 | //------------- | ||||||
368 | template<class T> | ||||||
369 | JFactory<T>* JEventLoop::GetFromFactory(vector<const T*> &t, const char *tag, data_source_t &data_source, bool allow_deftag) | ||||||
370 | { | ||||||
371 | // We need to find the factory providing data type T with | ||||||
372 | // tag given by "tag". | ||||||
373 | vector<JFactory_base*>::iterator iter=factories.begin(); | ||||||
374 | JFactory<T> *factory = NULL__null; | ||||||
375 | string className(T::static_className()); | ||||||
376 | |||||||
377 | // Check if a tag was specified for this data type to use for the | ||||||
378 | // default. | ||||||
379 | const char *mytag = tag==NULL__null ? "":tag; // protection against NULL tags | ||||||
380 | if(strlen(mytag)==0 && allow_deftag
| ||||||
381 | map<string, string>::const_iterator iter = default_tags.find(className); | ||||||
382 | if(iter!=default_tags.end())tag = iter->second.c_str(); | ||||||
383 | } | ||||||
384 | |||||||
385 | for(; iter!=factories.end(); iter++){ | ||||||
386 | // It turns out a long standing bug in g++ makes dynamic_cast return | ||||||
387 | // zero improperly when used on objects created on one side of | ||||||
388 | // a dynamically shared object (DSO) and the cast occurs on the | ||||||
389 | // other side. I saw bug reports ranging from 2001 to 2004. I saw | ||||||
390 | // saw it first-hand on LinuxEL4 using g++ 3.4.5. This is too bad | ||||||
391 | // since it is much more elegant (and safe) to use dynamic_cast. | ||||||
392 | // To avoid this problem which can occur with plugins, we check | ||||||
393 | // the name of the data classes are the same. (sigh) | ||||||
394 | //factory = dynamic_cast<JFactory<T> *>(*iter); | ||||||
395 | if(className == (*iter)->GetDataClassName())factory = (JFactory<T>*)(*iter); | ||||||
396 | if(factory == NULL__null)continue; | ||||||
397 | const char *factag = factory->Tag()==NULL__null ? "":factory->Tag(); | ||||||
398 | if(!strcmp(factag, tag)){ | ||||||
| |||||||
399 | break; | ||||||
400 | }else{ | ||||||
401 | factory=NULL__null; | ||||||
402 | } | ||||||
403 | } | ||||||
404 | |||||||
405 | // If factory not found, just return now | ||||||
406 | if(!factory){ | ||||||
407 | data_source = DATA_NOT_AVAILABLE; | ||||||
408 | return NULL__null; | ||||||
409 | } | ||||||
410 | |||||||
411 | // OK, we found the factory. If the evnt() routine has already | ||||||
412 | // been called, then just call the factory's Get() routine | ||||||
413 | // to return a copy of the existing data | ||||||
414 | if(factory->evnt_was_called()){ | ||||||
415 | factory->CopyFrom(t); | ||||||
416 | data_source = DATA_FROM_CACHE; | ||||||
417 | return factory; | ||||||
418 | } | ||||||
419 | |||||||
420 | // Next option is to get the objects from the data source | ||||||
421 | if(factory->GetCheckSourceFirst()){ | ||||||
422 | // If the object type/tag is found in the source, it | ||||||
423 | // will return NOERROR, even if there are zero instances | ||||||
424 | // of it. If it is not available in the source then it | ||||||
425 | // will return OBJECT_NOT_AVAILABLE. | ||||||
426 | |||||||
427 | jerror_t err = GetFromSource(t, factory); | ||||||
428 | if(err == NOERROR){ | ||||||
429 | // A return value of NOERROR means the source had the objects | ||||||
430 | // even if there were zero of them.(If the source had no | ||||||
431 | // information about the objects OBJECT_NOT_AVAILABLE would | ||||||
432 | // have been returned.) | ||||||
433 | // The GetFromSource() call will eventually lead to a call to | ||||||
434 | // the GetObjects() method of the concrete class derived | ||||||
435 | // from JEventSource. That routine should copy the object | ||||||
436 | // pointers into the factory using the factory's CopyTo() | ||||||
437 | // method which also sets the evnt_called flag for the factory. | ||||||
438 | // Note also that the "t" vector is then filled with a call | ||||||
439 | // to the factory's CopyFrom() method in JEvent::GetObjects(). | ||||||
440 | // All we need to do now is just set the factory pointers in | ||||||
441 | // the newly generated JObjects and return the factory pointer. | ||||||
442 | |||||||
443 | factory->SetFactoryPointers(); | ||||||
444 | data_source = DATA_FROM_SOURCE; | ||||||
445 | |||||||
446 | return factory; | ||||||
447 | } | ||||||
448 | } | ||||||
449 | |||||||
450 | // OK. It looks like we have to have the factory make this. | ||||||
451 | // Get pointers to data from the factory. | ||||||
452 | factory->Get(t); | ||||||
453 | factory->SetFactoryPointers(); | ||||||
454 | data_source = DATA_FROM_FACTORY; | ||||||
455 | |||||||
456 | return factory; | ||||||
457 | } | ||||||
458 | |||||||
459 | //------------- | ||||||
460 | // GetFromSource | ||||||
461 | //------------- | ||||||
462 | template<class T> | ||||||
463 | jerror_t JEventLoop::GetFromSource(vector<const T*> &t, JFactory_base *factory) | ||||||
464 | { | ||||||
465 | /// This tries to get objects from the event source. | ||||||
466 | /// "factory" must be a valid pointer to a JFactory | ||||||
467 | /// object since that will take ownership of the objects | ||||||
468 | /// created by the source. | ||||||
469 | /// This should usually be called from JEventLoop::GetFromFactory | ||||||
470 | /// which is called from JEventLoop::Get. The latter will | ||||||
471 | /// create a dummy JFactory of the proper flavor and tag if | ||||||
472 | /// one does not already exist so if objects exist in the | ||||||
473 | /// file without a corresponding factory to create them, they | ||||||
474 | /// can still be used. | ||||||
475 | if(!factory)throw OBJECT_NOT_AVAILABLE; | ||||||
476 | |||||||
477 | return event.GetObjects(t, factory); | ||||||
478 | } | ||||||
479 | |||||||
480 | //------------- | ||||||
481 | // CallStackStart | ||||||
482 | //------------- | ||||||
483 | inline void JEventLoop::CallStackStart(JEventLoop::call_stack_t &cs, const string &caller_name, const string &caller_tag, const string callee_name, const string callee_tag) | ||||||
484 | { | ||||||
485 | /// This is used to fill initial info into a call_stack_t stucture | ||||||
486 | /// for recording the call stack. It should be matched with a call | ||||||
487 | /// to CallStackEnd. It is normally called from the Get() method | ||||||
488 | /// above, but may also be used by external actors to manipulate | ||||||
489 | /// the call stack (presumably for good and not evil). | ||||||
490 | |||||||
491 | struct itimerval tmr; | ||||||
492 | getitimer(ITIMER_PROFITIMER_PROF, &tmr); | ||||||
493 | |||||||
494 | cs.caller_name = this->caller_name; | ||||||
495 | cs.caller_tag = this->caller_tag; | ||||||
496 | this->caller_name = cs.callee_name = callee_name; | ||||||
497 | this->caller_tag = cs.callee_tag = callee_tag; | ||||||
498 | cs.start_time = tmr.it_value.tv_sec + tmr.it_value.tv_usec/1.0E6; | ||||||
499 | } | ||||||
500 | |||||||
501 | //------------- | ||||||
502 | // CallStackEnd | ||||||
503 | //------------- | ||||||
504 | inline void JEventLoop::CallStackEnd(JEventLoop::call_stack_t &cs) | ||||||
505 | { | ||||||
506 | /// Complete a call stack entry. This should be matched | ||||||
507 | /// with a previous call to CallStackStart which was | ||||||
508 | /// used to fill the cs structure. | ||||||
509 | |||||||
510 | struct itimerval tmr; | ||||||
511 | getitimer(ITIMER_PROFITIMER_PROF, &tmr); | ||||||
512 | cs.end_time = tmr.it_value.tv_sec + tmr.it_value.tv_usec/1.0E6; | ||||||
513 | caller_name = cs.caller_name; | ||||||
514 | caller_tag = cs.caller_tag; | ||||||
515 | call_stack.push_back(cs); | ||||||
516 | } | ||||||
517 | |||||||
518 | //------------- | ||||||
519 | // CheckEventBoundary | ||||||
520 | //------------- | ||||||
521 | inline bool JEventLoop::CheckEventBoundary(uint64_t event_numberA, uint64_t event_numberB) | ||||||
522 | { | ||||||
523 | /// Check whether the two event numbers span one or more boundaries | ||||||
524 | /// in the calibration/conditions database for the current run number. | ||||||
525 | /// Return true if they do and false if they don't. The first parameter | ||||||
526 | /// "event_numberA" is also checked if it lands on a boundary in which | ||||||
527 | /// case true is also returned. If event_numberB lands on a boundary, | ||||||
528 | /// but event_numberA does not, then false is returned. | ||||||
529 | /// | ||||||
530 | /// This method is not expected to be called by a user. It is, however called, | ||||||
531 | /// everytime a JFactory's Get() method is called. | ||||||
532 | |||||||
533 | // Make sure our copy of the boundaries is up to date | ||||||
534 | if(event.GetRunNumber()!=event_boundaries_run){ | ||||||
535 | event_boundaries.clear(); // in case we can't get the JCalibration pointer | ||||||
536 | JCalibration *jcalib = GetJCalibration(); | ||||||
537 | if(jcalib)jcalib->GetEventBoundaries(event_boundaries); | ||||||
538 | event_boundaries_run = event.GetRunNumber(); | ||||||
539 | } | ||||||
540 | |||||||
541 | // Loop over boundaries | ||||||
542 | for(unsigned int i=0; i<event_boundaries.size(); i++){ | ||||||
543 | uint64_t eb = event_boundaries[i]; | ||||||
544 | if((eb - event_numberA)*(eb - event_numberB) < 0.0 || eb==event_numberA){ // think about it .... | ||||||
545 | // events span a boundary or is on a boundary. Return true | ||||||
546 | return true; | ||||||
547 | } | ||||||
548 | } | ||||||
549 | |||||||
550 | return false; | ||||||
551 | } | ||||||
552 | |||||||
553 | //------------- | ||||||
554 | // FindByID | ||||||
555 | //------------- | ||||||
556 | template<class T> | ||||||
557 | const T* JEventLoop::FindByID(JObject::oid_t id) | ||||||
558 | { | ||||||
559 | /// This is a templated method that can be used in place | ||||||
560 | /// of the non-templated FindByID(oid_t) method if one knows | ||||||
561 | /// the class of the object with the specified id. | ||||||
562 | /// This method is faster than calling the non-templated | ||||||
563 | /// FindByID and dynamic_cast-ing the JObject since | ||||||
564 | /// this will only search the objects of factories that | ||||||
565 | /// produce the desired data type. | ||||||
566 | /// This method will cast the JObject pointer to one | ||||||
567 | /// of the specified type. To use this method, | ||||||
568 | /// a type is specified in the call as follows: | ||||||
569 | /// | ||||||
570 | /// const DMyType *t = loop->FindByID<DMyType>(id); | ||||||
571 | |||||||
572 | // Loop over factories looking for ones that provide | ||||||
573 | // specified data type. | ||||||
574 | for(unsigned int i=0; i<factories.size(); i++){ | ||||||
575 | if(factories[i]->GetDataClassName() != T::static_className())continue; | ||||||
576 | |||||||
577 | // This factory provides data of type T. Search it for | ||||||
578 | // the object with the specified id. | ||||||
579 | const JObject *my_obj = factories[i]->GetByID(id); | ||||||
580 | if(my_obj)return dynamic_cast<const T*>(my_obj); | ||||||
581 | } | ||||||
582 | |||||||
583 | return NULL__null; | ||||||
584 | } | ||||||
585 | |||||||
586 | //------------- | ||||||
587 | // GetCalib (map) | ||||||
588 | //------------- | ||||||
589 | template<class T> | ||||||
590 | bool JEventLoop::GetCalib(string namepath, map<string,T> &vals) | ||||||
591 | { | ||||||
592 | /// Get the JCalibration object from JApplication for the run number of | ||||||
593 | /// the current event and call its Get() method to get the constants. | ||||||
594 | |||||||
595 | // Note that we could do this by making "vals" a generic type T thus, combining | ||||||
596 | // this with the vector version below. However, doing this explicitly will make | ||||||
597 | // it easier for the user to understand how to call us. | ||||||
598 | |||||||
599 | vals.clear(); | ||||||
600 | |||||||
601 | JCalibration *calib = GetJCalibration(); | ||||||
602 | if(!calib){ | ||||||
603 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<603<<" "<<"Unable to get JCalibration object for run "<<event.GetRunNumber()<<std::endl; | ||||||
604 | return true; | ||||||
605 | } | ||||||
606 | |||||||
607 | return calib->Get(namepath, vals, event.GetEventNumber()); | ||||||
608 | } | ||||||
609 | |||||||
610 | //------------- | ||||||
611 | // GetCalib (vector) | ||||||
612 | //------------- | ||||||
613 | template<class T> bool JEventLoop::GetCalib(string namepath, vector<T> &vals) | ||||||
614 | { | ||||||
615 | /// Get the JCalibration object from JApplication for the run number of | ||||||
616 | /// the current event and call its Get() method to get the constants. | ||||||
617 | |||||||
618 | vals.clear(); | ||||||
619 | |||||||
620 | JCalibration *calib = GetJCalibration(); | ||||||
621 | if(!calib){ | ||||||
622 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<622<<" "<<"Unable to get JCalibration object for run "<<event.GetRunNumber()<<std::endl; | ||||||
623 | return true; | ||||||
624 | } | ||||||
625 | |||||||
626 | return calib->Get(namepath, vals, event.GetEventNumber()); | ||||||
627 | } | ||||||
628 | |||||||
629 | //------------- | ||||||
630 | // GetCalib (single) | ||||||
631 | //------------- | ||||||
632 | template<class T> bool JEventLoop::GetCalib(string namepath, T &val) | ||||||
633 | { | ||||||
634 | /// This is a convenience method for getting a single entry. It | ||||||
635 | /// simply calls the vector version and returns the first entry. | ||||||
636 | /// It returns true if the vector version returns true AND there | ||||||
637 | /// is at least one entry in the vector. No check is made for there | ||||||
638 | /// there being more than one entry in the vector. | ||||||
639 | |||||||
640 | vector<T> vals; | ||||||
641 | bool ret = GetCalib(namepath, vals); | ||||||
642 | if(vals.empty()) return true; | ||||||
643 | val = vals[0]; | ||||||
644 | |||||||
645 | return ret; | ||||||
646 | } | ||||||
647 | |||||||
648 | //------------- | ||||||
649 | // GetGeom (map) | ||||||
650 | //------------- | ||||||
651 | template<class T> | ||||||
652 | bool JEventLoop::GetGeom(string namepath, map<string,T> &vals) | ||||||
653 | { | ||||||
654 | /// Get the JGeometry object from JApplication for the run number of | ||||||
655 | /// the current event and call its Get() method to get the constants. | ||||||
656 | |||||||
657 | // Note that we could do this by making "vals" a generic type T thus, combining | ||||||
658 | // this with the vector version below. However, doing this explicitly will make | ||||||
659 | // it easier for the user to understand how to call us. | ||||||
660 | |||||||
661 | vals.clear(); | ||||||
662 | |||||||
663 | JGeometry *geom = GetJGeometry(); | ||||||
664 | if(!geom){ | ||||||
665 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<665<<" "<<"Unable to get JGeometry object for run "<<event.GetRunNumber()<<std::endl; | ||||||
666 | return true; | ||||||
667 | } | ||||||
668 | |||||||
669 | return geom->Get(namepath, vals); | ||||||
670 | } | ||||||
671 | |||||||
672 | //------------- | ||||||
673 | // GetGeom (atomic) | ||||||
674 | //------------- | ||||||
675 | template<class T> bool JEventLoop::GetGeom(string namepath, T &val) | ||||||
676 | { | ||||||
677 | /// Get the JCalibration object from JApplication for the run number of | ||||||
678 | /// the current event and call its Get() method to get the constants. | ||||||
679 | |||||||
680 | JGeometry *geom = GetJGeometry(); | ||||||
681 | if(!geom){ | ||||||
682 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<682<<" "<<"Unable to get JGeometry object for run "<<event.GetRunNumber()<<std::endl; | ||||||
683 | return true; | ||||||
684 | } | ||||||
685 | |||||||
686 | return geom->Get(namepath, val); | ||||||
687 | } | ||||||
688 | |||||||
689 | //------------- | ||||||
690 | // SetRef | ||||||
691 | //------------- | ||||||
692 | template<class T> | ||||||
693 | void JEventLoop::SetRef(T *t) | ||||||
694 | { | ||||||
695 | pair<const char*, void*> p(typeid(T).name(), (void*)t); | ||||||
696 | user_refs.push_back(p); | ||||||
697 | } | ||||||
698 | |||||||
699 | //------------- | ||||||
700 | // GetResource | ||||||
701 | //------------- | ||||||
702 | template<class T> bool JEventLoop::GetResource(string namepath, T vals, int event_number) | ||||||
703 | { | ||||||
704 | JResourceManager *resource_manager = GetJResourceManager(); | ||||||
705 | if(!resource_manager){ | ||||||
706 | string mess = string("Unable to get the JResourceManager object (namepath=\"")+namepath+"\")"; | ||||||
707 | throw JException(mess); | ||||||
708 | } | ||||||
709 | |||||||
710 | return resource_manager->Get(namepath, vals, event_number); | ||||||
711 | } | ||||||
712 | |||||||
713 | //------------- | ||||||
714 | // GetRef | ||||||
715 | //------------- | ||||||
716 | template<class T> | ||||||
717 | T* JEventLoop::GetRef(void) | ||||||
718 | { | ||||||
719 | /// Get a user-defined reference (a pointer) | ||||||
720 | for(unsigned int i=0; i<user_refs.size(); i++){ | ||||||
721 | if(user_refs[i].first == typeid(T).name()) return (T*)user_refs[i].second; | ||||||
722 | } | ||||||
723 | |||||||
724 | return NULL__null; | ||||||
725 | } | ||||||
726 | |||||||
727 | //------------- | ||||||
728 | // GetRefsT | ||||||
729 | //------------- | ||||||
730 | template<class T> | ||||||
731 | vector<T*> JEventLoop::GetRefsT(void) | ||||||
732 | { | ||||||
733 | vector<T*> refs; | ||||||
734 | for(unsigned int i=0; i<user_refs.size(); i++){ | ||||||
735 | if(user_refs[i].first == typeid(T).name()){ | ||||||
736 | refs.push_back((T*)user_refs[i].second); | ||||||
737 | } | ||||||
738 | } | ||||||
739 | |||||||
740 | return refs; | ||||||
741 | } | ||||||
742 | |||||||
743 | //------------- | ||||||
744 | // RemoveRef | ||||||
745 | //------------- | ||||||
746 | template<class T> | ||||||
747 | void JEventLoop::RemoveRef(T *t) | ||||||
748 | { | ||||||
749 | vector<pair<const char*, void*> >::iterator iter; | ||||||
750 | for(iter=user_refs.begin(); iter!= user_refs.end(); iter++){ | ||||||
751 | if(iter->second == (void*)t){ | ||||||
752 | user_refs.erase(iter); | ||||||
753 | return; | ||||||
754 | } | ||||||
755 | } | ||||||
756 | _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h" <<":"<<756<<" "<<" Attempt to remove user reference not in event loop!" << std::endl; | ||||||
757 | } | ||||||
758 | |||||||
759 | |||||||
760 | #endif //__CINT__ __CLING__ | ||||||
761 | |||||||
762 | } // Close JANA namespace | ||||||
763 | |||||||
764 | |||||||
765 | |||||||
766 | #endif // _JEventLoop_ | ||||||
767 |
1 | // Iterators -*- C++ -*- |
2 | |
3 | // Copyright (C) 2001-2013 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /* |
26 | * |
27 | * Copyright (c) 1994 |
28 | * Hewlett-Packard Company |
29 | * |
30 | * Permission to use, copy, modify, distribute and sell this software |
31 | * and its documentation for any purpose is hereby granted without fee, |
32 | * provided that the above copyright notice appear in all copies and |
33 | * that both that copyright notice and this permission notice appear |
34 | * in supporting documentation. Hewlett-Packard Company makes no |
35 | * representations about the suitability of this software for any |
36 | * purpose. It is provided "as is" without express or implied warranty. |
37 | * |
38 | * |
39 | * Copyright (c) 1996-1998 |
40 | * Silicon Graphics Computer Systems, Inc. |
41 | * |
42 | * Permission to use, copy, modify, distribute and sell this software |
43 | * and its documentation for any purpose is hereby granted without fee, |
44 | * provided that the above copyright notice appear in all copies and |
45 | * that both that copyright notice and this permission notice appear |
46 | * in supporting documentation. Silicon Graphics makes no |
47 | * representations about the suitability of this software for any |
48 | * purpose. It is provided "as is" without express or implied warranty. |
49 | */ |
50 | |
51 | /** @file bits/stl_iterator.h |
52 | * This is an internal header file, included by other library headers. |
53 | * Do not attempt to use it directly. @headername{iterator} |
54 | * |
55 | * This file implements reverse_iterator, back_insert_iterator, |
56 | * front_insert_iterator, insert_iterator, __normal_iterator, and their |
57 | * supporting functions and overloaded operators. |
58 | */ |
59 | |
60 | #ifndef _STL_ITERATOR_H1 |
61 | #define _STL_ITERATOR_H1 1 |
62 | |
63 | #include <bits/cpp_type_traits.h> |
64 | #include <ext/type_traits.h> |
65 | #include <bits/move.h> |
66 | |
67 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
68 | { |
69 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
70 | |
71 | /** |
72 | * @addtogroup iterators |
73 | * @{ |
74 | */ |
75 | |
76 | // 24.4.1 Reverse iterators |
77 | /** |
78 | * Bidirectional and random access iterators have corresponding reverse |
79 | * %iterator adaptors that iterate through the data structure in the |
80 | * opposite direction. They have the same signatures as the corresponding |
81 | * iterators. The fundamental relation between a reverse %iterator and its |
82 | * corresponding %iterator @c i is established by the identity: |
83 | * @code |
84 | * &*(reverse_iterator(i)) == &*(i - 1) |
85 | * @endcode |
86 | * |
87 | * <em>This mapping is dictated by the fact that while there is always a |
88 | * pointer past the end of an array, there might not be a valid pointer |
89 | * before the beginning of an array.</em> [24.4.1]/1,2 |
90 | * |
91 | * Reverse iterators can be tricky and surprising at first. Their |
92 | * semantics make sense, however, and the trickiness is a side effect of |
93 | * the requirement that the iterators must be safe. |
94 | */ |
95 | template<typename _Iterator> |
96 | class reverse_iterator |
97 | : public iterator<typename iterator_traits<_Iterator>::iterator_category, |
98 | typename iterator_traits<_Iterator>::value_type, |
99 | typename iterator_traits<_Iterator>::difference_type, |
100 | typename iterator_traits<_Iterator>::pointer, |
101 | typename iterator_traits<_Iterator>::reference> |
102 | { |
103 | protected: |
104 | _Iterator current; |
105 | |
106 | typedef iterator_traits<_Iterator> __traits_type; |
107 | |
108 | public: |
109 | typedef _Iterator iterator_type; |
110 | typedef typename __traits_type::difference_type difference_type; |
111 | typedef typename __traits_type::pointer pointer; |
112 | typedef typename __traits_type::reference reference; |
113 | |
114 | /** |
115 | * The default constructor value-initializes member @p current. |
116 | * If it is a pointer, that means it is zero-initialized. |
117 | */ |
118 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
119 | // 235 No specification of default ctor for reverse_iterator |
120 | reverse_iterator() : current() { } |
121 | |
122 | /** |
123 | * This %iterator will move in the opposite direction that @p x does. |
124 | */ |
125 | explicit |
126 | reverse_iterator(iterator_type __x) : current(__x) { } |
127 | |
128 | /** |
129 | * The copy constructor is normal. |
130 | */ |
131 | reverse_iterator(const reverse_iterator& __x) |
132 | : current(__x.current) { } |
133 | |
134 | /** |
135 | * A %reverse_iterator across other types can be copied if the |
136 | * underlying %iterator can be converted to the type of @c current. |
137 | */ |
138 | template<typename _Iter> |
139 | reverse_iterator(const reverse_iterator<_Iter>& __x) |
140 | : current(__x.base()) { } |
141 | |
142 | /** |
143 | * @return @c current, the %iterator used for underlying work. |
144 | */ |
145 | iterator_type |
146 | base() const |
147 | { return current; } |
148 | |
149 | /** |
150 | * @return A reference to the value at @c --current |
151 | * |
152 | * This requires that @c --current is dereferenceable. |
153 | * |
154 | * @warning This implementation requires that for an iterator of the |
155 | * underlying iterator type, @c x, a reference obtained by |
156 | * @c *x remains valid after @c x has been modified or |
157 | * destroyed. This is a bug: http://gcc.gnu.org/PR51823 |
158 | */ |
159 | reference |
160 | operator*() const |
161 | { |
162 | _Iterator __tmp = current; |
163 | return *--__tmp; |
164 | } |
165 | |
166 | /** |
167 | * @return A pointer to the value at @c --current |
168 | * |
169 | * This requires that @c --current is dereferenceable. |
170 | */ |
171 | pointer |
172 | operator->() const |
173 | { return &(operator*()); } |
174 | |
175 | /** |
176 | * @return @c *this |
177 | * |
178 | * Decrements the underlying iterator. |
179 | */ |
180 | reverse_iterator& |
181 | operator++() |
182 | { |
183 | --current; |
184 | return *this; |
185 | } |
186 | |
187 | /** |
188 | * @return The original value of @c *this |
189 | * |
190 | * Decrements the underlying iterator. |
191 | */ |
192 | reverse_iterator |
193 | operator++(int) |
194 | { |
195 | reverse_iterator __tmp = *this; |
196 | --current; |
197 | return __tmp; |
198 | } |
199 | |
200 | /** |
201 | * @return @c *this |
202 | * |
203 | * Increments the underlying iterator. |
204 | */ |
205 | reverse_iterator& |
206 | operator--() |
207 | { |
208 | ++current; |
209 | return *this; |
210 | } |
211 | |
212 | /** |
213 | * @return A reverse_iterator with the previous value of @c *this |
214 | * |
215 | * Increments the underlying iterator. |
216 | */ |
217 | reverse_iterator |
218 | operator--(int) |
219 | { |
220 | reverse_iterator __tmp = *this; |
221 | ++current; |
222 | return __tmp; |
223 | } |
224 | |
225 | /** |
226 | * @return A reverse_iterator that refers to @c current - @a __n |
227 | * |
228 | * The underlying iterator must be a Random Access Iterator. |
229 | */ |
230 | reverse_iterator |
231 | operator+(difference_type __n) const |
232 | { return reverse_iterator(current - __n); } |
233 | |
234 | /** |
235 | * @return *this |
236 | * |
237 | * Moves the underlying iterator backwards @a __n steps. |
238 | * The underlying iterator must be a Random Access Iterator. |
239 | */ |
240 | reverse_iterator& |
241 | operator+=(difference_type __n) |
242 | { |
243 | current -= __n; |
244 | return *this; |
245 | } |
246 | |
247 | /** |
248 | * @return A reverse_iterator that refers to @c current - @a __n |
249 | * |
250 | * The underlying iterator must be a Random Access Iterator. |
251 | */ |
252 | reverse_iterator |
253 | operator-(difference_type __n) const |
254 | { return reverse_iterator(current + __n); } |
255 | |
256 | /** |
257 | * @return *this |
258 | * |
259 | * Moves the underlying iterator forwards @a __n steps. |
260 | * The underlying iterator must be a Random Access Iterator. |
261 | */ |
262 | reverse_iterator& |
263 | operator-=(difference_type __n) |
264 | { |
265 | current += __n; |
266 | return *this; |
267 | } |
268 | |
269 | /** |
270 | * @return The value at @c current - @a __n - 1 |
271 | * |
272 | * The underlying iterator must be a Random Access Iterator. |
273 | */ |
274 | reference |
275 | operator[](difference_type __n) const |
276 | { return *(*this + __n); } |
277 | }; |
278 | |
279 | //@{ |
280 | /** |
281 | * @param __x A %reverse_iterator. |
282 | * @param __y A %reverse_iterator. |
283 | * @return A simple bool. |
284 | * |
285 | * Reverse iterators forward many operations to their underlying base() |
286 | * iterators. Others are implemented in terms of one another. |
287 | * |
288 | */ |
289 | template<typename _Iterator> |
290 | inline bool |
291 | operator==(const reverse_iterator<_Iterator>& __x, |
292 | const reverse_iterator<_Iterator>& __y) |
293 | { return __x.base() == __y.base(); } |
294 | |
295 | template<typename _Iterator> |
296 | inline bool |
297 | operator<(const reverse_iterator<_Iterator>& __x, |
298 | const reverse_iterator<_Iterator>& __y) |
299 | { return __y.base() < __x.base(); } |
300 | |
301 | template<typename _Iterator> |
302 | inline bool |
303 | operator!=(const reverse_iterator<_Iterator>& __x, |
304 | const reverse_iterator<_Iterator>& __y) |
305 | { return !(__x == __y); } |
306 | |
307 | template<typename _Iterator> |
308 | inline bool |
309 | operator>(const reverse_iterator<_Iterator>& __x, |
310 | const reverse_iterator<_Iterator>& __y) |
311 | { return __y < __x; } |
312 | |
313 | template<typename _Iterator> |
314 | inline bool |
315 | operator<=(const reverse_iterator<_Iterator>& __x, |
316 | const reverse_iterator<_Iterator>& __y) |
317 | { return !(__y < __x); } |
318 | |
319 | template<typename _Iterator> |
320 | inline bool |
321 | operator>=(const reverse_iterator<_Iterator>& __x, |
322 | const reverse_iterator<_Iterator>& __y) |
323 | { return !(__x < __y); } |
324 | |
325 | template<typename _Iterator> |
326 | inline typename reverse_iterator<_Iterator>::difference_type |
327 | operator-(const reverse_iterator<_Iterator>& __x, |
328 | const reverse_iterator<_Iterator>& __y) |
329 | { return __y.base() - __x.base(); } |
330 | |
331 | template<typename _Iterator> |
332 | inline reverse_iterator<_Iterator> |
333 | operator+(typename reverse_iterator<_Iterator>::difference_type __n, |
334 | const reverse_iterator<_Iterator>& __x) |
335 | { return reverse_iterator<_Iterator>(__x.base() - __n); } |
336 | |
337 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
338 | // DR 280. Comparison of reverse_iterator to const reverse_iterator. |
339 | template<typename _IteratorL, typename _IteratorR> |
340 | inline bool |
341 | operator==(const reverse_iterator<_IteratorL>& __x, |
342 | const reverse_iterator<_IteratorR>& __y) |
343 | { return __x.base() == __y.base(); } |
344 | |
345 | template<typename _IteratorL, typename _IteratorR> |
346 | inline bool |
347 | operator<(const reverse_iterator<_IteratorL>& __x, |
348 | const reverse_iterator<_IteratorR>& __y) |
349 | { return __y.base() < __x.base(); } |
350 | |
351 | template<typename _IteratorL, typename _IteratorR> |
352 | inline bool |
353 | operator!=(const reverse_iterator<_IteratorL>& __x, |
354 | const reverse_iterator<_IteratorR>& __y) |
355 | { return !(__x == __y); } |
356 | |
357 | template<typename _IteratorL, typename _IteratorR> |
358 | inline bool |
359 | operator>(const reverse_iterator<_IteratorL>& __x, |
360 | const reverse_iterator<_IteratorR>& __y) |
361 | { return __y < __x; } |
362 | |
363 | template<typename _IteratorL, typename _IteratorR> |
364 | inline bool |
365 | operator<=(const reverse_iterator<_IteratorL>& __x, |
366 | const reverse_iterator<_IteratorR>& __y) |
367 | { return !(__y < __x); } |
368 | |
369 | template<typename _IteratorL, typename _IteratorR> |
370 | inline bool |
371 | operator>=(const reverse_iterator<_IteratorL>& __x, |
372 | const reverse_iterator<_IteratorR>& __y) |
373 | { return !(__x < __y); } |
374 | |
375 | template<typename _IteratorL, typename _IteratorR> |
376 | #if __cplusplus201103L >= 201103L |
377 | // DR 685. |
378 | inline auto |
379 | operator-(const reverse_iterator<_IteratorL>& __x, |
380 | const reverse_iterator<_IteratorR>& __y) |
381 | -> decltype(__y.base() - __x.base()) |
382 | #else |
383 | inline typename reverse_iterator<_IteratorL>::difference_type |
384 | operator-(const reverse_iterator<_IteratorL>& __x, |
385 | const reverse_iterator<_IteratorR>& __y) |
386 | #endif |
387 | { return __y.base() - __x.base(); } |
388 | //@} |
389 | |
390 | // 24.4.2.2.1 back_insert_iterator |
391 | /** |
392 | * @brief Turns assignment into insertion. |
393 | * |
394 | * These are output iterators, constructed from a container-of-T. |
395 | * Assigning a T to the iterator appends it to the container using |
396 | * push_back. |
397 | * |
398 | * Tip: Using the back_inserter function to create these iterators can |
399 | * save typing. |
400 | */ |
401 | template<typename _Container> |
402 | class back_insert_iterator |
403 | : public iterator<output_iterator_tag, void, void, void, void> |
404 | { |
405 | protected: |
406 | _Container* container; |
407 | |
408 | public: |
409 | /// A nested typedef for the type of whatever container you used. |
410 | typedef _Container container_type; |
411 | |
412 | /// The only way to create this %iterator is with a container. |
413 | explicit |
414 | back_insert_iterator(_Container& __x) : container(&__x) { } |
415 | |
416 | /** |
417 | * @param __value An instance of whatever type |
418 | * container_type::const_reference is; presumably a |
419 | * reference-to-const T for container<T>. |
420 | * @return This %iterator, for chained operations. |
421 | * |
422 | * This kind of %iterator doesn't really have a @a position in the |
423 | * container (you can think of the position as being permanently at |
424 | * the end, if you like). Assigning a value to the %iterator will |
425 | * always append the value to the end of the container. |
426 | */ |
427 | #if __cplusplus201103L < 201103L |
428 | back_insert_iterator& |
429 | operator=(typename _Container::const_reference __value) |
430 | { |
431 | container->push_back(__value); |
432 | return *this; |
433 | } |
434 | #else |
435 | back_insert_iterator& |
436 | operator=(const typename _Container::value_type& __value) |
437 | { |
438 | container->push_back(__value); |
439 | return *this; |
440 | } |
441 | |
442 | back_insert_iterator& |
443 | operator=(typename _Container::value_type&& __value) |
444 | { |
445 | container->push_back(std::move(__value)); |
446 | return *this; |
447 | } |
448 | #endif |
449 | |
450 | /// Simply returns *this. |
451 | back_insert_iterator& |
452 | operator*() |
453 | { return *this; } |
454 | |
455 | /// Simply returns *this. (This %iterator does not @a move.) |
456 | back_insert_iterator& |
457 | operator++() |
458 | { return *this; } |
459 | |
460 | /// Simply returns *this. (This %iterator does not @a move.) |
461 | back_insert_iterator |
462 | operator++(int) |
463 | { return *this; } |
464 | }; |
465 | |
466 | /** |
467 | * @param __x A container of arbitrary type. |
468 | * @return An instance of back_insert_iterator working on @p __x. |
469 | * |
470 | * This wrapper function helps in creating back_insert_iterator instances. |
471 | * Typing the name of the %iterator requires knowing the precise full |
472 | * type of the container, which can be tedious and impedes generic |
473 | * programming. Using this function lets you take advantage of automatic |
474 | * template parameter deduction, making the compiler match the correct |
475 | * types for you. |
476 | */ |
477 | template<typename _Container> |
478 | inline back_insert_iterator<_Container> |
479 | back_inserter(_Container& __x) |
480 | { return back_insert_iterator<_Container>(__x); } |
481 | |
482 | /** |
483 | * @brief Turns assignment into insertion. |
484 | * |
485 | * These are output iterators, constructed from a container-of-T. |
486 | * Assigning a T to the iterator prepends it to the container using |
487 | * push_front. |
488 | * |
489 | * Tip: Using the front_inserter function to create these iterators can |
490 | * save typing. |
491 | */ |
492 | template<typename _Container> |
493 | class front_insert_iterator |
494 | : public iterator<output_iterator_tag, void, void, void, void> |
495 | { |
496 | protected: |
497 | _Container* container; |
498 | |
499 | public: |
500 | /// A nested typedef for the type of whatever container you used. |
501 | typedef _Container container_type; |
502 | |
503 | /// The only way to create this %iterator is with a container. |
504 | explicit front_insert_iterator(_Container& __x) : container(&__x) { } |
505 | |
506 | /** |
507 | * @param __value An instance of whatever type |
508 | * container_type::const_reference is; presumably a |
509 | * reference-to-const T for container<T>. |
510 | * @return This %iterator, for chained operations. |
511 | * |
512 | * This kind of %iterator doesn't really have a @a position in the |
513 | * container (you can think of the position as being permanently at |
514 | * the front, if you like). Assigning a value to the %iterator will |
515 | * always prepend the value to the front of the container. |
516 | */ |
517 | #if __cplusplus201103L < 201103L |
518 | front_insert_iterator& |
519 | operator=(typename _Container::const_reference __value) |
520 | { |
521 | container->push_front(__value); |
522 | return *this; |
523 | } |
524 | #else |
525 | front_insert_iterator& |
526 | operator=(const typename _Container::value_type& __value) |
527 | { |
528 | container->push_front(__value); |
529 | return *this; |
530 | } |
531 | |
532 | front_insert_iterator& |
533 | operator=(typename _Container::value_type&& __value) |
534 | { |
535 | container->push_front(std::move(__value)); |
536 | return *this; |
537 | } |
538 | #endif |
539 | |
540 | /// Simply returns *this. |
541 | front_insert_iterator& |
542 | operator*() |
543 | { return *this; } |
544 | |
545 | /// Simply returns *this. (This %iterator does not @a move.) |
546 | front_insert_iterator& |
547 | operator++() |
548 | { return *this; } |
549 | |
550 | /// Simply returns *this. (This %iterator does not @a move.) |
551 | front_insert_iterator |
552 | operator++(int) |
553 | { return *this; } |
554 | }; |
555 | |
556 | /** |
557 | * @param __x A container of arbitrary type. |
558 | * @return An instance of front_insert_iterator working on @p x. |
559 | * |
560 | * This wrapper function helps in creating front_insert_iterator instances. |
561 | * Typing the name of the %iterator requires knowing the precise full |
562 | * type of the container, which can be tedious and impedes generic |
563 | * programming. Using this function lets you take advantage of automatic |
564 | * template parameter deduction, making the compiler match the correct |
565 | * types for you. |
566 | */ |
567 | template<typename _Container> |
568 | inline front_insert_iterator<_Container> |
569 | front_inserter(_Container& __x) |
570 | { return front_insert_iterator<_Container>(__x); } |
571 | |
572 | /** |
573 | * @brief Turns assignment into insertion. |
574 | * |
575 | * These are output iterators, constructed from a container-of-T. |
576 | * Assigning a T to the iterator inserts it in the container at the |
577 | * %iterator's position, rather than overwriting the value at that |
578 | * position. |
579 | * |
580 | * (Sequences will actually insert a @e copy of the value before the |
581 | * %iterator's position.) |
582 | * |
583 | * Tip: Using the inserter function to create these iterators can |
584 | * save typing. |
585 | */ |
586 | template<typename _Container> |
587 | class insert_iterator |
588 | : public iterator<output_iterator_tag, void, void, void, void> |
589 | { |
590 | protected: |
591 | _Container* container; |
592 | typename _Container::iterator iter; |
593 | |
594 | public: |
595 | /// A nested typedef for the type of whatever container you used. |
596 | typedef _Container container_type; |
597 | |
598 | /** |
599 | * The only way to create this %iterator is with a container and an |
600 | * initial position (a normal %iterator into the container). |
601 | */ |
602 | insert_iterator(_Container& __x, typename _Container::iterator __i) |
603 | : container(&__x), iter(__i) {} |
604 | |
605 | /** |
606 | * @param __value An instance of whatever type |
607 | * container_type::const_reference is; presumably a |
608 | * reference-to-const T for container<T>. |
609 | * @return This %iterator, for chained operations. |
610 | * |
611 | * This kind of %iterator maintains its own position in the |
612 | * container. Assigning a value to the %iterator will insert the |
613 | * value into the container at the place before the %iterator. |
614 | * |
615 | * The position is maintained such that subsequent assignments will |
616 | * insert values immediately after one another. For example, |
617 | * @code |
618 | * // vector v contains A and Z |
619 | * |
620 | * insert_iterator i (v, ++v.begin()); |
621 | * i = 1; |
622 | * i = 2; |
623 | * i = 3; |
624 | * |
625 | * // vector v contains A, 1, 2, 3, and Z |
626 | * @endcode |
627 | */ |
628 | #if __cplusplus201103L < 201103L |
629 | insert_iterator& |
630 | operator=(typename _Container::const_reference __value) |
631 | { |
632 | iter = container->insert(iter, __value); |
633 | ++iter; |
634 | return *this; |
635 | } |
636 | #else |
637 | insert_iterator& |
638 | operator=(const typename _Container::value_type& __value) |
639 | { |
640 | iter = container->insert(iter, __value); |
641 | ++iter; |
642 | return *this; |
643 | } |
644 | |
645 | insert_iterator& |
646 | operator=(typename _Container::value_type&& __value) |
647 | { |
648 | iter = container->insert(iter, std::move(__value)); |
649 | ++iter; |
650 | return *this; |
651 | } |
652 | #endif |
653 | |
654 | /// Simply returns *this. |
655 | insert_iterator& |
656 | operator*() |
657 | { return *this; } |
658 | |
659 | /// Simply returns *this. (This %iterator does not @a move.) |
660 | insert_iterator& |
661 | operator++() |
662 | { return *this; } |
663 | |
664 | /// Simply returns *this. (This %iterator does not @a move.) |
665 | insert_iterator& |
666 | operator++(int) |
667 | { return *this; } |
668 | }; |
669 | |
670 | /** |
671 | * @param __x A container of arbitrary type. |
672 | * @return An instance of insert_iterator working on @p __x. |
673 | * |
674 | * This wrapper function helps in creating insert_iterator instances. |
675 | * Typing the name of the %iterator requires knowing the precise full |
676 | * type of the container, which can be tedious and impedes generic |
677 | * programming. Using this function lets you take advantage of automatic |
678 | * template parameter deduction, making the compiler match the correct |
679 | * types for you. |
680 | */ |
681 | template<typename _Container, typename _Iterator> |
682 | inline insert_iterator<_Container> |
683 | inserter(_Container& __x, _Iterator __i) |
684 | { |
685 | return insert_iterator<_Container>(__x, |
686 | typename _Container::iterator(__i)); |
687 | } |
688 | |
689 | // @} group iterators |
690 | |
691 | _GLIBCXX_END_NAMESPACE_VERSION |
692 | } // namespace |
693 | |
694 | namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
695 | { |
696 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
697 | |
698 | // This iterator adapter is @a normal in the sense that it does not |
699 | // change the semantics of any of the operators of its iterator |
700 | // parameter. Its primary purpose is to convert an iterator that is |
701 | // not a class, e.g. a pointer, into an iterator that is a class. |
702 | // The _Container parameter exists solely so that different containers |
703 | // using this template can instantiate different types, even if the |
704 | // _Iterator parameter is the same. |
705 | using std::iterator_traits; |
706 | using std::iterator; |
707 | template<typename _Iterator, typename _Container> |
708 | class __normal_iterator |
709 | { |
710 | protected: |
711 | _Iterator _M_current; |
712 | |
713 | typedef iterator_traits<_Iterator> __traits_type; |
714 | |
715 | public: |
716 | typedef _Iterator iterator_type; |
717 | typedef typename __traits_type::iterator_category iterator_category; |
718 | typedef typename __traits_type::value_type value_type; |
719 | typedef typename __traits_type::difference_type difference_type; |
720 | typedef typename __traits_type::reference reference; |
721 | typedef typename __traits_type::pointer pointer; |
722 | |
723 | _GLIBCXX_CONSTEXPRconstexpr __normal_iterator() : _M_current(_Iterator()) { } |
724 | |
725 | explicit |
726 | __normal_iterator(const _Iterator& __i) : _M_current(__i) { } |
727 | |
728 | // Allow iterator to const_iterator conversion |
729 | template<typename _Iter> |
730 | __normal_iterator(const __normal_iterator<_Iter, |
731 | typename __enable_if< |
732 | (std::__are_same<_Iter, typename _Container::pointer>::__value), |
733 | _Container>::__type>& __i) |
734 | : _M_current(__i.base()) { } |
735 | |
736 | // Forward iterator requirements |
737 | reference |
738 | operator*() const |
739 | { return *_M_current; } |
740 | |
741 | pointer |
742 | operator->() const |
743 | { return _M_current; } |
744 | |
745 | __normal_iterator& |
746 | operator++() |
747 | { |
748 | ++_M_current; |
749 | return *this; |
750 | } |
751 | |
752 | __normal_iterator |
753 | operator++(int) |
754 | { return __normal_iterator(_M_current++); } |
755 | |
756 | // Bidirectional iterator requirements |
757 | __normal_iterator& |
758 | operator--() |
759 | { |
760 | --_M_current; |
761 | return *this; |
762 | } |
763 | |
764 | __normal_iterator |
765 | operator--(int) |
766 | { return __normal_iterator(_M_current--); } |
767 | |
768 | // Random access iterator requirements |
769 | reference |
770 | operator[](const difference_type& __n) const |
771 | { return _M_current[__n]; } |
772 | |
773 | __normal_iterator& |
774 | operator+=(const difference_type& __n) |
775 | { _M_current += __n; return *this; } |
776 | |
777 | __normal_iterator |
778 | operator+(const difference_type& __n) const |
779 | { return __normal_iterator(_M_current + __n); } |
780 | |
781 | __normal_iterator& |
782 | operator-=(const difference_type& __n) |
783 | { _M_current -= __n; return *this; } |
784 | |
785 | __normal_iterator |
786 | operator-(const difference_type& __n) const |
787 | { return __normal_iterator(_M_current - __n); } |
788 | |
789 | const _Iterator& |
790 | base() const |
791 | { return _M_current; } |
792 | }; |
793 | |
794 | // Note: In what follows, the left- and right-hand-side iterators are |
795 | // allowed to vary in types (conceptually in cv-qualification) so that |
796 | // comparison between cv-qualified and non-cv-qualified iterators be |
797 | // valid. However, the greedy and unfriendly operators in std::rel_ops |
798 | // will make overload resolution ambiguous (when in scope) if we don't |
799 | // provide overloads whose operands are of the same type. Can someone |
800 | // remind me what generic programming is about? -- Gaby |
801 | |
802 | // Forward iterator requirements |
803 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
804 | inline bool |
805 | operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, |
806 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
807 | { return __lhs.base() == __rhs.base(); } |
808 | |
809 | template<typename _Iterator, typename _Container> |
810 | inline bool |
811 | operator==(const __normal_iterator<_Iterator, _Container>& __lhs, |
812 | const __normal_iterator<_Iterator, _Container>& __rhs) |
813 | { return __lhs.base() == __rhs.base(); } |
814 | |
815 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
816 | inline bool |
817 | operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, |
818 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
819 | { return __lhs.base() != __rhs.base(); } |
820 | |
821 | template<typename _Iterator, typename _Container> |
822 | inline bool |
823 | operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, |
824 | const __normal_iterator<_Iterator, _Container>& __rhs) |
825 | { return __lhs.base() != __rhs.base(); } |
826 | |
827 | // Random access iterator requirements |
828 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
829 | inline bool |
830 | operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, |
831 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
832 | { return __lhs.base() < __rhs.base(); } |
833 | |
834 | template<typename _Iterator, typename _Container> |
835 | inline bool |
836 | operator<(const __normal_iterator<_Iterator, _Container>& __lhs, |
837 | const __normal_iterator<_Iterator, _Container>& __rhs) |
838 | { return __lhs.base() < __rhs.base(); } |
839 | |
840 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
841 | inline bool |
842 | operator>(const __normal_iterator<_IteratorL, _Container>& __lhs, |
843 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
844 | { return __lhs.base() > __rhs.base(); } |
845 | |
846 | template<typename _Iterator, typename _Container> |
847 | inline bool |
848 | operator>(const __normal_iterator<_Iterator, _Container>& __lhs, |
849 | const __normal_iterator<_Iterator, _Container>& __rhs) |
850 | { return __lhs.base() > __rhs.base(); } |
851 | |
852 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
853 | inline bool |
854 | operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs, |
855 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
856 | { return __lhs.base() <= __rhs.base(); } |
857 | |
858 | template<typename _Iterator, typename _Container> |
859 | inline bool |
860 | operator<=(const __normal_iterator<_Iterator, _Container>& __lhs, |
861 | const __normal_iterator<_Iterator, _Container>& __rhs) |
862 | { return __lhs.base() <= __rhs.base(); } |
863 | |
864 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
865 | inline bool |
866 | operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs, |
867 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
868 | { return __lhs.base() >= __rhs.base(); } |
869 | |
870 | template<typename _Iterator, typename _Container> |
871 | inline bool |
872 | operator>=(const __normal_iterator<_Iterator, _Container>& __lhs, |
873 | const __normal_iterator<_Iterator, _Container>& __rhs) |
874 | { return __lhs.base() >= __rhs.base(); } |
875 | |
876 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
877 | // According to the resolution of DR179 not only the various comparison |
878 | // operators but also operator- must accept mixed iterator/const_iterator |
879 | // parameters. |
880 | template<typename _IteratorL, typename _IteratorR, typename _Container> |
881 | #if __cplusplus201103L >= 201103L |
882 | // DR 685. |
883 | inline auto |
884 | operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, |
885 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
886 | -> decltype(__lhs.base() - __rhs.base()) |
887 | #else |
888 | inline typename __normal_iterator<_IteratorL, _Container>::difference_type |
889 | operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, |
890 | const __normal_iterator<_IteratorR, _Container>& __rhs) |
891 | #endif |
892 | { return __lhs.base() - __rhs.base(); } |
893 | |
894 | template<typename _Iterator, typename _Container> |
895 | inline typename __normal_iterator<_Iterator, _Container>::difference_type |
896 | operator-(const __normal_iterator<_Iterator, _Container>& __lhs, |
897 | const __normal_iterator<_Iterator, _Container>& __rhs) |
898 | { return __lhs.base() - __rhs.base(); } |
899 | |
900 | template<typename _Iterator, typename _Container> |
901 | inline __normal_iterator<_Iterator, _Container> |
902 | operator+(typename __normal_iterator<_Iterator, _Container>::difference_type |
903 | __n, const __normal_iterator<_Iterator, _Container>& __i) |
904 | { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); } |
905 | |
906 | _GLIBCXX_END_NAMESPACE_VERSION |
907 | } // namespace |
908 | |
909 | #if __cplusplus201103L >= 201103L |
910 | |
911 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
912 | { |
913 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
914 | |
915 | /** |
916 | * @addtogroup iterators |
917 | * @{ |
918 | */ |
919 | |
920 | // 24.4.3 Move iterators |
921 | /** |
922 | * Class template move_iterator is an iterator adapter with the same |
923 | * behavior as the underlying iterator except that its dereference |
924 | * operator implicitly converts the value returned by the underlying |
925 | * iterator's dereference operator to an rvalue reference. Some |
926 | * generic algorithms can be called with move iterators to replace |
927 | * copying with moving. |
928 | */ |
929 | template<typename _Iterator> |
930 | class move_iterator |
931 | { |
932 | protected: |
933 | _Iterator _M_current; |
934 | |
935 | typedef iterator_traits<_Iterator> __traits_type; |
936 | |
937 | public: |
938 | typedef _Iterator iterator_type; |
939 | typedef typename __traits_type::iterator_category iterator_category; |
940 | typedef typename __traits_type::value_type value_type; |
941 | typedef typename __traits_type::difference_type difference_type; |
942 | // NB: DR 680. |
943 | typedef _Iterator pointer; |
944 | typedef value_type&& reference; |
945 | |
946 | move_iterator() |
947 | : _M_current() { } |
948 | |
949 | explicit |
950 | move_iterator(iterator_type __i) |
951 | : _M_current(__i) { } |
952 | |
953 | template<typename _Iter> |
954 | move_iterator(const move_iterator<_Iter>& __i) |
955 | : _M_current(__i.base()) { } |
956 | |
957 | iterator_type |
958 | base() const |
959 | { return _M_current; } |
960 | |
961 | reference |
962 | operator*() const |
963 | { return std::move(*_M_current); } |
964 | |
965 | pointer |
966 | operator->() const |
967 | { return _M_current; } |
968 | |
969 | move_iterator& |
970 | operator++() |
971 | { |
972 | ++_M_current; |
973 | return *this; |
974 | } |
975 | |
976 | move_iterator |
977 | operator++(int) |
978 | { |
979 | move_iterator __tmp = *this; |
980 | ++_M_current; |
981 | return __tmp; |
982 | } |
983 | |
984 | move_iterator& |
985 | operator--() |
986 | { |
987 | --_M_current; |
988 | return *this; |
989 | } |
990 | |
991 | move_iterator |
992 | operator--(int) |
993 | { |
994 | move_iterator __tmp = *this; |
995 | --_M_current; |
996 | return __tmp; |
997 | } |
998 | |
999 | move_iterator |
1000 | operator+(difference_type __n) const |
1001 | { return move_iterator(_M_current + __n); } |
1002 | |
1003 | move_iterator& |
1004 | operator+=(difference_type __n) |
1005 | { |
1006 | _M_current += __n; |
1007 | return *this; |
1008 | } |
1009 | |
1010 | move_iterator |
1011 | operator-(difference_type __n) const |
1012 | { return move_iterator(_M_current - __n); } |
1013 | |
1014 | move_iterator& |
1015 | operator-=(difference_type __n) |
1016 | { |
1017 | _M_current -= __n; |
1018 | return *this; |
1019 | } |
1020 | |
1021 | reference |
1022 | operator[](difference_type __n) const |
1023 | { return std::move(_M_current[__n]); } |
1024 | }; |
1025 | |
1026 | // Note: See __normal_iterator operators note from Gaby to understand |
1027 | // why there are always 2 versions for most of the move_iterator |
1028 | // operators. |
1029 | template<typename _IteratorL, typename _IteratorR> |
1030 | inline bool |
1031 | operator==(const move_iterator<_IteratorL>& __x, |
1032 | const move_iterator<_IteratorR>& __y) |
1033 | { return __x.base() == __y.base(); } |
1034 | |
1035 | template<typename _Iterator> |
1036 | inline bool |
1037 | operator==(const move_iterator<_Iterator>& __x, |
1038 | const move_iterator<_Iterator>& __y) |
1039 | { return __x.base() == __y.base(); } |
1040 | |
1041 | template<typename _IteratorL, typename _IteratorR> |
1042 | inline bool |
1043 | operator!=(const move_iterator<_IteratorL>& __x, |
1044 | const move_iterator<_IteratorR>& __y) |
1045 | { return !(__x == __y); } |
1046 | |
1047 | template<typename _Iterator> |
1048 | inline bool |
1049 | operator!=(const move_iterator<_Iterator>& __x, |
1050 | const move_iterator<_Iterator>& __y) |
1051 | { return !(__x == __y); } |
1052 | |
1053 | template<typename _IteratorL, typename _IteratorR> |
1054 | inline bool |
1055 | operator<(const move_iterator<_IteratorL>& __x, |
1056 | const move_iterator<_IteratorR>& __y) |
1057 | { return __x.base() < __y.base(); } |
1058 | |
1059 | template<typename _Iterator> |
1060 | inline bool |
1061 | operator<(const move_iterator<_Iterator>& __x, |
1062 | const move_iterator<_Iterator>& __y) |
1063 | { return __x.base() < __y.base(); } |
1064 | |
1065 | template<typename _IteratorL, typename _IteratorR> |
1066 | inline bool |
1067 | operator<=(const move_iterator<_IteratorL>& __x, |
1068 | const move_iterator<_IteratorR>& __y) |
1069 | { return !(__y < __x); } |
1070 | |
1071 | template<typename _Iterator> |
1072 | inline bool |
1073 | operator<=(const move_iterator<_Iterator>& __x, |
1074 | const move_iterator<_Iterator>& __y) |
1075 | { return !(__y < __x); } |
1076 | |
1077 | template<typename _IteratorL, typename _IteratorR> |
1078 | inline bool |
1079 | operator>(const move_iterator<_IteratorL>& __x, |
1080 | const move_iterator<_IteratorR>& __y) |
1081 | { return __y < __x; } |
1082 | |
1083 | template<typename _Iterator> |
1084 | inline bool |
1085 | operator>(const move_iterator<_Iterator>& __x, |
1086 | const move_iterator<_Iterator>& __y) |
1087 | { return __y < __x; } |
1088 | |
1089 | template<typename _IteratorL, typename _IteratorR> |
1090 | inline bool |
1091 | operator>=(const move_iterator<_IteratorL>& __x, |
1092 | const move_iterator<_IteratorR>& __y) |
1093 | { return !(__x < __y); } |
1094 | |
1095 | template<typename _Iterator> |
1096 | inline bool |
1097 | operator>=(const move_iterator<_Iterator>& __x, |
1098 | const move_iterator<_Iterator>& __y) |
1099 | { return !(__x < __y); } |
1100 | |
1101 | // DR 685. |
1102 | template<typename _IteratorL, typename _IteratorR> |
1103 | inline auto |
1104 | operator-(const move_iterator<_IteratorL>& __x, |
1105 | const move_iterator<_IteratorR>& __y) |
1106 | -> decltype(__x.base() - __y.base()) |
1107 | { return __x.base() - __y.base(); } |
1108 | |
1109 | template<typename _Iterator> |
1110 | inline auto |
1111 | operator-(const move_iterator<_Iterator>& __x, |
1112 | const move_iterator<_Iterator>& __y) |
1113 | -> decltype(__x.base() - __y.base()) |
1114 | { return __x.base() - __y.base(); } |
1115 | |
1116 | template<typename _Iterator> |
1117 | inline move_iterator<_Iterator> |
1118 | operator+(typename move_iterator<_Iterator>::difference_type __n, |
1119 | const move_iterator<_Iterator>& __x) |
1120 | { return __x + __n; } |
1121 | |
1122 | template<typename _Iterator> |
1123 | inline move_iterator<_Iterator> |
1124 | make_move_iterator(_Iterator __i) |
1125 | { return move_iterator<_Iterator>(__i); } |
1126 | |
1127 | template<typename _Iterator, typename _ReturnType |
1128 | = typename conditional<__move_if_noexcept_cond |
1129 | <typename iterator_traits<_Iterator>::value_type>::value, |
1130 | _Iterator, move_iterator<_Iterator>>::type> |
1131 | inline _ReturnType |
1132 | __make_move_if_noexcept_iterator(_Iterator __i) |
1133 | { return _ReturnType(__i); } |
1134 | |
1135 | // @} group iterators |
1136 | |
1137 | _GLIBCXX_END_NAMESPACE_VERSION |
1138 | } // namespace |
1139 | |
1140 | #define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) std::make_move_iterator(_Iter) |
1141 | #define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) \ |
1142 | std::__make_move_if_noexcept_iterator(_Iter) |
1143 | #else |
1144 | #define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) (_Iter) |
1145 | #define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) (_Iter) |
1146 | #endif // C++11 |
1147 | |
1148 | #endif |