Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TDirectory.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id: 65b4f3646f4e5b2fa77218ba786b7fe4e16e27be $
2// Author: Rene Brun 28/11/94
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11#include <cstdlib>
12
13#include "Strlen.h"
14#include "strlcpy.h"
15#include "TDirectory.h"
16#include "TBuffer.h"
17#include "TClassTable.h"
18#include "TInterpreter.h"
19#include "THashList.h"
20#include "TBrowser.h"
21#include "TROOT.h"
22#include "TError.h"
23#include "TClass.h"
24#include "TRegexp.h"
25#include "TSystem.h"
26#include "TVirtualMutex.h"
27#include "TThreadSlots.h"
28#include "TMethod.h"
29
30#include "TSpinLockGuard.h"
31
33
34const Int_t kMaxLen = 2048;
35
36static std::atomic_flag *GetCurrentDirectoryLock()
37{
38 thread_local std::atomic_flag gDirectory_lock = ATOMIC_FLAG_INIT;
39 return &gDirectory_lock;
40}
41
42/** \class TDirectory
43\ingroup Base
44
45Describe directory structure in memory.
46*/
47
49
50////////////////////////////////////////////////////////////////////////////////
51/// Directory default constructor.
52
54{
55 // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
56 std::atomic_flag_clear( &fSpinLock );
57}
58
59////////////////////////////////////////////////////////////////////////////////
60/// Create a new Directory.
61///
62/// A new directory with name,title is created in the current directory
63/// The directory header information is immediately saved in the file
64/// A new key is added in the parent directory
65///
66/// When this constructor is called from a class directly derived
67/// from TDirectory, the third argument classname MUST be specified.
68/// In this case, classname must be the name of the derived class.
69///
70/// Note that the directory name cannot contain slashes.
71
72TDirectory::TDirectory(const char *name, const char *title, Option_t * /*classname*/, TDirectory* initMotherDir)
73 : TNamed(name, title)
74{
75 // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
76 std::atomic_flag_clear( &fSpinLock );
77
78 if (!initMotherDir) initMotherDir = gDirectory;
79
80 if (strchr(name,'/')) {
81 ::Error("TDirectory::TDirectory","directory name (%s) cannot contain a slash", name);
82 gDirectory = nullptr;
83 return;
84 }
85 if (strlen(GetName()) == 0) {
86 ::Error("TDirectory::TDirectory","directory name cannot be \"\"");
87 gDirectory = nullptr;
88 return;
89 }
90
91 BuildDirectory(initMotherDir ? initMotherDir->GetFile() : nullptr, initMotherDir);
92}
93
94////////////////////////////////////////////////////////////////////////////////
95/// Destructor.
96
98{
99 // Use gROOTLocal to avoid triggering undesired initialization of gROOT.
100 // For example in compiled C++ programs that don't use it directly.
102 delete fList;
103 return; //when called by TROOT destructor
104 }
105
106 if (fList) {
107 if (!fList->IsUsingRWLock())
108 Fatal("~TDirectory","In %s:%p the fList (%p) is not using the RWLock\n",
109 GetName(),this,fList);
110 fList->Delete("slow");
112 }
113
115
116 TDirectory* mom = GetMotherDir();
117
118 if (mom) {
119 mom->Remove(this);
120 }
121
122 if (gDebug) {
123 Info("~TDirectory", "dtor called for %s", GetName());
124 }
125}
126
127
128////////////////////////////////////////////////////////////////////////////////
129/// Set the current directory to null.
130/// This is called from the TContext destructor. Since the destructor is
131/// inline, we do not want to have it directly use a global variable.
132
134{
135 gDirectory = nullptr;
136}
137
138////////////////////////////////////////////////////////////////////////////////
139/// Destructor.
140///
141/// Reset the current directory to its previous state.
142
144{
145 fActiveDestructor = true;
146 if (fDirectory) {
147 // UnregisterContext must not be virtual to allow
148 // this to work even with fDirectory set to nullptr.
149 (*fDirectory).UnregisterContext(this);
150 // While we were waiting for the lock, the TDirectory
151 // may have been deleted by another thread, so
152 // we need to recheck the value of fDirectory.
153 if (fDirectory)
154 (*fDirectory).cd();
155 else
156 CdNull();
157 } else {
158 CdNull();
159 }
160 fActiveDestructor = false;
161 while(fDirectoryWait);
162}
163
164////////////////////////////////////////////////////////////////////////////////
165/// Sets the flag controlling the automatic add objects like histograms, TGraph2D, etc
166/// in memory
167///
168/// By default (fAddDirectory = kTRUE), these objects are automatically added
169/// to the list of objects in memory.
170/// Note that in the classes like TH1, TGraph2D supporting this facility,
171/// one object can be removed from its support directory
172/// by calling object->SetDirectory(nullptr) or object->SetDirectory(dir) to add it
173/// to the list of objects in the directory dir.
174///
175/// NOTE that this is a static function. To call it, use:
176/// ~~~ {.cpp}
177/// TDirectory::AddDirectory
178/// ~~~
179
181{
182 fgAddDirectory = add;
183}
184
185////////////////////////////////////////////////////////////////////////////////
186/// Static function: see TDirectory::AddDirectory for more comments.
187
189{
190 return fgAddDirectory;
191}
192
193////////////////////////////////////////////////////////////////////////////////
194/// Append object to this directory.
195///
196/// If `replace` is true:
197/// remove any existing objects with the same name (if the name is not "")
198
199void TDirectory::Append(TObject *obj, Bool_t replace /* = kFALSE */)
200{
201 if (!obj || !fList) return;
202
203 if (replace && obj->GetName() && obj->GetName()[0]) {
204 TObject *old;
205 while (nullptr != (old = GetList()->FindObject(obj->GetName()))) {
206 Warning("Append","Replacing existing %s: %s (Potential memory leak).",
207 obj->IsA()->GetName(),obj->GetName());
209 if (func) {
210 func(old,nullptr);
211 } else {
212 Remove(old);
213 }
214 }
215 }
216
217 fList->Add(obj);
218 // A priori, a `TDirectory` object is assumed to not have shared ownership.
219 // If it is, let's rely on the user to update the bit.
220 if (!dynamic_cast<TDirectory*>(obj))
221 obj->SetBit(kMustCleanup);
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// Browse the content of the directory.
226
228{
229 if (b) {
230 TObject *obj = nullptr;
231 TIter nextin(fList);
232
233 cd();
234
235 //Add objects that are only in memory
236 while ((obj = nextin())) {
237 b->Add(obj, obj->GetName());
238 }
239 }
240}
241
242////////////////////////////////////////////////////////////////////////////////
243/// Initialise directory to defaults.
244///
245/// If directory is created via default ctor (when dir is read from file)
246/// don't add it here to the directory since its name is not yet known.
247/// It will be added to the directory in TKey::ReadObj().
248
249void TDirectory::BuildDirectory(TFile* /*motherFile*/, TDirectory* motherDir)
250{
251 fList = new THashList(100,50);
252 fList->UseRWLock();
253 fMother = motherDir;
255
256 // Build is done and is the last part of the constructor (and is not
257 // being called from the derived classes) so we can publish.
258 if (motherDir && strlen(GetName()) != 0) motherDir->Append(this);
259}
260
261////////////////////////////////////////////////////////////////////////////////
262/// Clean the pointers to this object (gDirectory, TContext, etc.).
263
265{
266 std::vector<TContext*> extraWait;
267
268 {
270
271 while (fContext) {
272 const auto next = fContext->fNext;
273 const auto ctxt = fContext;
274 ctxt->fDirectoryWait = true;
275
276 // If fDirectory is assigned to gROOT but we do not unregister ctxt
277 // (and/or stop unregister for gROOT) then ~TContext will call Unregister on gROOT.
278 // Then unregister of this ctxt and its Previous context can actually be run
279 // in parallel (this takes the gROOT lock, Previous takes the lock of fDirectory)
280 // and thus step on each other.
281 ctxt->fDirectory = nullptr; // Can not be gROOT
282
283 if (ctxt->fActiveDestructor) {
284 extraWait.push_back(fContext);
285 } else {
286 ctxt->fDirectoryWait = false;
287 }
288 fContext = next;
289 }
290
291 // Now loop through the set of thread local 'gDirectory' that
292 // have a one point or another pointed to this directory.
293 for (auto &ptr : fGDirectories) {
294 // If the thread local gDirectory still point to this directory
295 // we need to reset it using the following sematic:
296 // we fall back to the mother/owner of this directory or gROOTLocal
297 // if there is no parent or nullptr if the current object is gROOTLocal.
298 if (ptr->load() == this) {
299 TDirectory *next = GetMotherDir();
300 if (!next || next == this) {
301 if (this == ROOT::Internal::gROOTLocal) { /// in that case next == this.
302 next = nullptr;
303 } else {
305 }
306 } else {
307 // We can not use 'cd' as this would access the current thread
308 // rather than the thread corresponding to that gDirectory.
309 next->RegisterGDirectory(ptr);
310 }
311 // Actually do the update of the thread local gDirectory
312 // using its object specific lock.
313 auto This = this;
314 ptr->compare_exchange_strong(This, next);
315 }
316 }
317 }
318 for(auto &&context : extraWait) {
319 // Wait until the TContext is done spinning
320 // over the lock.
321 while(context->fActiveDestructor);
322 // And now let the TContext destructor finish.
323 context->fDirectoryWait = false;
324 }
325
326 // Wait until all register attempts are done.
327 while(fContextPeg) {}
328
329}
330
331////////////////////////////////////////////////////////////////////////////////
332/// Fast execution of 'new TBufferFile(TBuffer::kWrite,10000), without having
333/// a compile time circular dependency ... alternatively we could (should?)
334/// introduce yet another abstract interface.
335
337{
338 typedef void (*tcling_callfunc_Wrapper_t)(void*, int, void**, void*);
339 static tcling_callfunc_Wrapper_t creator = nullptr;
340 if (!creator) {
342 TClass *c = TClass::GetClass("TBufferFile");
343 TMethod *m = c->GetMethodWithPrototype("TBufferFile","TBuffer::EMode,Int_t",kFALSE,ROOT::kExactMatch);
344 creator = (tcling_callfunc_Wrapper_t)( m->InterfaceMethod() );
345 }
347 Int_t size = 10000;
348 void *args[] = { &mode, &size };
350 creator(nullptr,2,args,&result);
351 return result;
352}
353
354////////////////////////////////////////////////////////////////////////////////
355/// Clone an object.
356/// This function is called when the directory is not a TDirectoryFile.
357/// This version has to load the I/O package, hence via Cling.
358///
359/// If autoadd is true and if the object class has a
360/// DirectoryAutoAdd function, it will be called at the end of the
361/// function with the parameter gDirector. This usually means that
362/// the object will be appended to the current ROOT directory.
363
364TObject *TDirectory::CloneObject(const TObject *obj, Bool_t autoadd /* = kTRUE */)
365{
366 // if no default ctor return immediately (error issued by New())
367 char *pobj = (char*)obj->IsA()->New();
368 if (!pobj) {
369 Fatal("CloneObject","Failed to create new object");
370 return nullptr;
371 }
372
373 Int_t baseOffset = obj->IsA()->GetBaseClassOffset(TObject::Class());
374 if (baseOffset==-1) {
375 // cl does not inherit from TObject.
376 // Since this is not supported in this function, the only reason we could reach this code
377 // is because something is screwed up in the ROOT code.
378 Fatal("CloneObject","Incorrect detection of the inheritance from TObject for class %s.\n",
379 obj->IsA()->GetName());
380 }
381 TObject *newobj = (TObject*)(pobj+baseOffset);
382
383 //create a buffer where the object will be streamed
384 //We are forced to go via the I/O package (ie TBufferFile).
385 //Invoking TBufferFile via CINT will automatically load the I/O library
386 TBuffer *buffer = R__CreateBuffer();
387 if (!buffer) {
388 Fatal("CloneObject","Not able to create a TBuffer!");
389 return nullptr;
390 }
391 buffer->MapObject(obj); //register obj in map to handle self reference
392 const_cast<TObject*>(obj)->Streamer(*buffer);
393
394 // read new object from buffer
395 buffer->SetReadMode();
396 buffer->ResetMap();
397 buffer->SetBufferOffset(0);
398 buffer->MapObject(newobj); //register obj in map to handle self reference
399 newobj->Streamer(*buffer);
400 newobj->ResetBit(kIsReferenced);
401 newobj->ResetBit(kCanDelete);
402
403 delete buffer;
404 if (autoadd) {
406 if (func) {
407 func(newobj,this);
408 }
409 }
410 return newobj;
411}
412
413////////////////////////////////////////////////////////////////////////////////
414/// Return the (address of) a shared pointer to the struct holding the
415/// actual thread local gDirectory pointer and the atomic_flag for its lock.
417{
418 using shared_ptr_type = TDirectory::SharedGDirectory_t;
419
420 // Note in previous implementation every time gDirectory was lookup in
421 // a thread, if it was set to nullptr it would be reset to gROOT. This
422 // was unexpected and this routine is not re-introducing this issue.
423 thread_local shared_ptr_type currentDirectory =
424 std::make_shared<shared_ptr_type::element_type>(ROOT::Internal::gROOTLocal);
425
426 return currentDirectory;
427}
428
429////////////////////////////////////////////////////////////////////////////////
430/// Return the current directory for the current thread.
431
432std::atomic<TDirectory*> &TDirectory::CurrentDirectory()
433{
434 return *GetSharedLocalCurrentDirectory().get();
435}
436
437////////////////////////////////////////////////////////////////////////////////
438/// Find a directory using apath.
439/// It apath is null or empty, returns "this" directory.
440/// Otherwise use apath to find a directory.
441/// The absolute path syntax is: `file.root:/dir1/dir2`
442///
443/// where file.root is the file and /dir1/dir2 the desired subdirectory
444/// in the file. Relative syntax is relative to "this" directory. E.g: `../aa`.
445/// Returns 0 in case path does not exist.
446/// If printError is true, use Error with 'funcname' to issue an error message.
447
449 Bool_t printError, const char *funcname)
450{
451 Int_t nch = 0;
452 if (apath) nch = strlen(apath);
453 if (!nch) {
454 return this;
455 }
456
457 if (funcname==nullptr || strlen(funcname)==0) funcname = "GetDirectory";
458
459 TDirectory *result = this;
460
461 char *path = new char[nch+1]; path[0] = 0;
462 if (nch) strlcpy(path,apath,nch+1);
463 char *s = (char*)strrchr(path, ':');
464 if (s) {
465 *s = '\0';
467 TDirectory *f = (TDirectory *)gROOT->GetListOfFiles()->FindObject(path);
468 if (!f && !strcmp(gROOT->GetName(), path)) f = gROOT;
469 if (s) *s = ':';
470 if (f) {
471 result = f;
472 if (s && *(s+1)) result = f->GetDirectory(s+1,printError,funcname);
473 delete [] path; return result;
474 } else {
475 if (printError) Error(funcname, "No such file %s", path);
476 delete [] path; return nullptr;
477 }
478 }
479
480 // path starts with a slash (assumes current file)
481 if (path[0] == '/') {
482 TDirectory *td = gROOT;
483 result = td->GetDirectory(path+1,printError,funcname);
484 delete [] path; return result;
485 }
486
487 TObject *obj;
488 char *slash = (char*)strchr(path,'/');
489 if (!slash) { // we are at the lowest level
490 if (!strcmp(path, "..")) {
492 delete [] path; return result;
493 }
494 obj = Get(path);
495 if (!obj) {
496 if (printError) Error(funcname,"Unknown directory %s", path);
497 delete [] path; return nullptr;
498 }
499
500 //Check return object is a directory
501 if (!obj->InheritsFrom(TDirectory::Class())) {
502 if (printError) Error(funcname,"Object %s is not a directory", path);
503 delete [] path; return nullptr;
504 }
505 delete [] path; return (TDirectory*)obj;
506 }
507
508 TString subdir(path);
509 slash = (char*)strchr(subdir.Data(),'/');
510 *slash = 0;
511 //Get object with path from current directory/file
512 if (!strcmp(subdir, "..")) {
513 TDirectory* mom = GetMotherDir();
514 if (mom)
515 result = mom->GetDirectory(slash+1,printError,funcname);
516 delete [] path; return result;
517 }
518 obj = Get(subdir);
519 if (!obj) {
520 if (printError) Error(funcname,"Unknown directory %s", subdir.Data());
521 delete [] path; return nullptr;
522 }
523
524 //Check return object is a directory
525 if (!obj->InheritsFrom(TDirectory::Class())) {
526 if (printError) Error(funcname,"Object %s is not a directory", subdir.Data());
527 delete [] path; return nullptr;
528 }
529 result = ((TDirectory*)obj)->GetDirectory(slash+1,printError,funcname);
530 delete [] path; return result;
531}
532
533////////////////////////////////////////////////////////////////////////////////
534/// Change current directory to "this" directory.
535///
536/// Returns kTRUE (it's guaranteed to succeed).
537
539{
540 auto &thread_local_gdirectory = GetSharedLocalCurrentDirectory();
541
542 RegisterGDirectory(thread_local_gdirectory);
543
544 thread_local_gdirectory->exchange(this);
545
546 return kTRUE;
547}
548
549////////////////////////////////////////////////////////////////////////////////
550/// Change current directory to "this" directory or to the directory described
551/// by the path if given one.
552///
553/// Using path one can change the current directory to "path". The absolute path
554/// syntax is: `file.root:/dir1/dir2`
555/// where `file.root` is the file and `/dir1/dir2` the desired subdirectory
556/// in the file.
557///
558/// Relative syntax is relative to "this" directory. E.g: `../aa`.
559///
560/// Returns kTRUE in case of success.
561
562Bool_t TDirectory::cd(const char *path)
563{
564 return cd1(path);
565}
566
567////////////////////////////////////////////////////////////////////////////////
568/// Change current directory to "this" directory or to the directory described
569/// by the path if given one.
570///
571/// Using path one can
572/// change the current directory to "path". The absolute path syntax is:
573/// `file.root:/dir1/dir2`
574/// where `file.root` is the file and `/dir1/dir2` the desired subdirectory
575/// in the file.
576///
577/// Relative syntax is relative to "this" directory. E.g: `../aa`.
578///
579/// Returns kFALSE in case path does not exist.
580
581Bool_t TDirectory::cd1(const char *apath)
582{
583 if (!apath || !apath[0])
584 return this->cd();
585
586 TDirectory *where = GetDirectory(apath, kTRUE, "cd");
587 if (where) {
588 where->cd();
589 return kTRUE;
590 }
591 return kFALSE;
592}
593
594////////////////////////////////////////////////////////////////////////////////
595/// Change current directory to "path". The absolute path syntax is:
596/// `file.root:/dir1/dir2`
597/// where file.root is the file and `/dir1/dir2 the desired subdirectory
598/// in the file.
599/// Relative syntax is relative to the current directory `gDirectory`, e.g.: `../aa`.
600///
601/// Returns kTRUE in case of success.
602
603Bool_t TDirectory::Cd(const char *path)
604{
605 return Cd1(path);
606}
607
608////////////////////////////////////////////////////////////////////////////////
609/// Change current directory to "path". The path syntax is:
610/// `file.root:/dir1/dir2`
611/// where file.root is the file and `/dir1/dir2` the desired subdirectory
612/// in the file.
613/// Relative syntax is relative to the current directory `gDirectory`, e.g.: `../aa`.
614///
615/// Returns kFALSE in case path does not exist.
616
617Bool_t TDirectory::Cd1(const char *apath)
618{
619 // null path is always true (i.e. stay in the current directory)
620 if (!apath || !apath[0])
621 return kTRUE;
622
623 TDirectory *where = gDirectory->GetDirectory(apath, kTRUE, "Cd");
624 if (where) {
625 where->cd();
626 return kTRUE;
627 }
628 return kFALSE;
629}
630
631////////////////////////////////////////////////////////////////////////////////
632/// Delete all objects from a Directory list.
633
635{
636 if (fList) fList->Clear();
637}
638
639////////////////////////////////////////////////////////////////////////////////
640/// Delete all objects from memory and directory structure itself.
641/// if option is "slow", iterate through the containers in a way to can handle
642/// 'external' modification (induced by recursions)
643/// if option is "nodelete", write the TDirectory but do not delete the contained
644/// objects.
646{
647 if (!fList) {
648 return;
649 }
650
651 // Save the directory key list and header
652 Save();
653
654 Bool_t nodelete = option ? (!strcmp(option, "nodelete") ? kTRUE : kFALSE) : kFALSE;
655
656 if (!nodelete) {
657 Bool_t slow = option ? (!strcmp(option, "slow") ? kTRUE : kFALSE) : kFALSE;
658 if (!slow) {
659 // Check if it is wise to use the fast deletion path.
660 TObjLink *lnk = fList->FirstLink();
661 while (lnk) {
662 if (lnk->GetObject()->IsA() == TDirectory::Class()) {
663 slow = kTRUE;
664 break;
665 }
666 lnk = lnk->Next();
667 }
668 }
669
670 // Delete objects from directory list, this in turn, recursively closes all
671 // sub-directories (that were allocated on the heap)
672 // if this dir contains subdirs, we must use the slow option for Delete!
673 // we must avoid "slow" as much as possible, in particular Delete("slow")
674 // with a large number of objects (eg >10^5) would take for ever.
675 if (slow) fList->Delete("slow");
676 else fList->Delete();
677 }
678
680}
681
682////////////////////////////////////////////////////////////////////////////////
683/// Delete all objects from memory.
684
686{
687 fList->Delete("slow");
688}
689
690////////////////////////////////////////////////////////////////////////////////
691/// Delete Objects or/and keys in a directory.
692///
693/// - namecycle has the format name;cycle
694/// - namecycle = "" same as namecycle ="T*"
695/// - name = * means all
696/// - cycle = * means all cycles (memory and keys)
697/// - cycle = "" or cycle = 9999 ==> apply to a memory object
698/// When name=* use T* to delete subdirectories also
699///
700/// To delete one directory, you must specify the directory cycle,
701/// eg. `file.Delete("dir1;1");`
702///
703/// examples:
704/// - foo : delete object named foo in memory
705/// - foo* : delete all objects with a name starting with foo
706/// - foo;1 : delete cycle 1 of foo on file
707/// - foo;* : delete all cycles of foo on file and also from memory
708/// - *;2 : delete all objects on file having the cycle 2
709/// - *;* : delete all objects from memory and file
710/// - T*;* : delete all objects from memory and file and all subdirectories
711
712void TDirectory::Delete(const char *namecycle)
713{
714 if (gDebug)
715 Info("Delete","Call for this = %s namecycle = %s",
716 GetName(), (namecycle ? namecycle : "null"));
717
718 TDirectory::TContext ctxt(this);
719 Short_t cycle;
720 char name[kMaxLen];
721 DecodeNameCycle(namecycle, name, cycle, kMaxLen);
722
723 Int_t deleteall = 0;
724 Int_t deletetree = 0;
725 if(strcmp(name,"*") == 0) deleteall = 1;
726 if(strcmp(name,"*T") == 0){ deleteall = 1; deletetree = 1;}
727 if(strcmp(name,"T*") == 0){ deleteall = 1; deletetree = 1;}
728 if(namecycle==nullptr || !namecycle[0]){ deleteall = 1; deletetree = 1;}
729 TRegexp re(name,kTRUE);
730 TString s;
731 Int_t deleteOK = 0;
732
733//*-*---------------------Case of Object in memory---------------------
734// ========================
735 if (cycle >= 9999 ) {
736 TNamed *idcur;
737 TIter next(fList);
738 while ((idcur = (TNamed *) next())) {
739 deleteOK = 0;
740 s = idcur->GetName();
741 if (deleteall || s.Index(re) != kNPOS) {
742 deleteOK = 1;
743 if (idcur->IsA() == TDirectory::Class()) {
744 deleteOK = 2;
745 if (!deletetree && deleteall) deleteOK = 0;
746 }
747 }
748 if (deleteOK != 0) {
749 fList->Remove(idcur);
750 if (deleteOK==2) {
751 // read subdirectories to correctly delete them
752 if (deletetree)
753 ((TDirectory*) idcur)->ReadAll("dirs");
754 idcur->Delete(deletetree ? "T*;*" : "*");
755 delete idcur;
756 } else
757 idcur->Delete(name);
758 }
759 }
760 }
761}
762
763////////////////////////////////////////////////////////////////////////////////
764/// Fill Graphics Structure and Paint.
765///
766/// Loop on all objects (memory or file) and all subdirectories
767
769{
770 fList->R__FOR_EACH(TObject,Draw)(option);
771}
772
773////////////////////////////////////////////////////////////////////////////////
774/// Find object in the list of memory objects.
775
777{
778 return fList->FindObject(obj);
779}
780
781////////////////////////////////////////////////////////////////////////////////
782/// Find object by name in the list of memory objects.
783
785{
786 return fList->FindObject(name);
787}
788
789////////////////////////////////////////////////////////////////////////////////
790/// Find object by name in the list of memory objects of the current
791/// directory or its sub-directories.
792/// After this call the current directory is not changed.
793/// To automatically set the current directory where the object is found,
794/// use FindKeyAny(aname)->ReadObj().
795
796TObject *TDirectory::FindObjectAny(const char *aname) const
797{
798 //object may be already in the list of objects in memory
799 TObject *obj = fList->FindObject(aname);
800 if (obj) return obj;
801
802 //try with subdirectories
803 TIter next(fList);
804 while( (obj = next()) ) {
805 if (obj->IsA()->InheritsFrom(TDirectory::Class())) {
806 TDirectory* subdir = static_cast<TDirectory*>(obj);
807 TObject *subobj = subdir->TDirectory::FindObjectAny(aname); // Explicitly recurse into _this_ exact function.
808 if (subobj) {
809 return subobj;
810 }
811 }
812 }
813 return nullptr;
814}
815
816////////////////////////////////////////////////////////////////////////////////
817/// Return pointer to object identified by namecycle.
818///
819/// namecycle has the format name;cycle
820/// - name = * is illegal, cycle = * is illegal
821/// - cycle = "" or cycle = 9999 ==> apply to a memory object
822///
823/// examples:
824/// - foo : get object named foo in memory
825/// if object is not in memory, try with highest cycle from file
826/// - foo;1 : get cycle 1 of foo on file
827///
828/// The retrieved object should in principle derive from TObject.
829/// If not, the function TDirectory::GetObject should be called.
830/// However, this function will still work for a non-TObject, providing that
831/// the calling application cast the return type to the correct type (which
832/// is the actual type of the object).
833///
834/// NOTE:
835///
836/// The method GetObject offer better protection and avoid the need
837/// for any cast:
838/// ~~~ {.cpp}
839/// MyClass *obj;
840/// directory->GetObject("some object",obj);
841/// if (obj) { ... the object exist and inherits from MyClass ... }
842/// ~~~
843///
844/// VERY IMPORTANT NOTE:
845///
846/// In case the class of this object derives from TObject but not
847/// as a first inheritance, one must use dynamic_cast<>().
848/// #### Example 1: Normal case:
849/// ~~~ {.cpp}
850/// class MyClass : public TObject, public AnotherClass
851/// ~~~
852/// then on return, one can do:
853/// ~~~ {.cpp}
854/// MyClass *obj = (MyClass*)directory->Get("some object of MyClass");
855/// ~~~
856/// #### Example 2: Special case:
857/// ~~~ {.cpp}
858/// class MyClass : public AnotherClass, public TObject
859/// ~~~
860/// then on return, one must do:
861/// ~~~ {.cpp}
862/// MyClass *obj = dynamic_cast<MyClass*>(directory->Get("some object of MyClass"));
863/// ~~~
864/// Of course, dynamic_cast<> can also be used in the example 1.
865
866TObject *TDirectory::Get(const char *namecycle)
867{
868 Short_t cycle;
869 char name[kMaxLen];
870
871 DecodeNameCycle(namecycle, name, cycle, kMaxLen);
872 char *namobj = name;
873 Int_t nch = strlen(name);
874 for (Int_t i = nch-1; i > 0; i--) {
875 if (name[i] == '/') {
876 name[i] = 0;
877 TDirectory* dirToSearch=GetDirectory(name);
878 namobj = name + i + 1;
879 name[i] = '/';
880 return dirToSearch ? dirToSearch->Get(namobj) : nullptr;
881 }
882 }
883
884//*-*---------------------Case of Object in memory---------------------
885// ========================
886 TObject *idcur = fList->FindObject(namobj);
887 if (idcur) {
888 if (idcur==this && strlen(namobj)!=0) {
889 // The object has the same name has the directory and
890 // that's what we picked-up! We just need to ignore
891 // it ...
892 idcur = nullptr;
893 } else if (cycle == 9999) {
894 return idcur;
895 } else {
896 if (idcur->InheritsFrom(TCollection::Class()))
897 idcur->Delete(); // delete also list elements
898 delete idcur;
899 idcur = nullptr;
900 }
901 }
902 return idcur;
903}
904
905////////////////////////////////////////////////////////////////////////////////
906/// Return pointer to object identified by namecycle.
907/// The returned object may or may not derive from TObject.
908///
909/// - namecycle has the format name;cycle
910/// - name = * is illegal, cycle = * is illegal
911/// - cycle = "" or cycle = 9999 ==> apply to a memory object
912///
913/// VERY IMPORTANT NOTE:
914///
915/// The calling application must cast the returned object to
916/// the final type, e.g.
917/// ~~~ {.cpp}
918/// MyClass *obj = (MyClass*)directory->GetObject("some object of MyClass");
919/// ~~~
920
921void *TDirectory::GetObjectUnchecked(const char *namecycle)
922{
923 return GetObjectChecked(namecycle,(TClass *)nullptr);
924}
925
926////////////////////////////////////////////////////////////////////////////////
927/// See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl)
928
929void *TDirectory::GetObjectChecked(const char *namecycle, const char* classname)
930{
931 return GetObjectChecked(namecycle, TClass::GetClass(classname));
932}
933
934
935////////////////////////////////////////////////////////////////////////////////
936/// Return pointer to object identified by namecycle if and only if the actual
937/// object is a type suitable to be stored as a pointer to a "expectedClass"
938/// If expectedClass is null, no check is performed.
939///
940/// namecycle has the format `name;cycle`
941/// - name = * is illegal, cycle = * is illegal
942/// - cycle = "" or cycle = 9999 ==> apply to a memory object
943///
944/// VERY IMPORTANT NOTE:
945///
946/// The calling application must cast the returned pointer to
947/// the type described by the 2 arguments (i.e. cl):
948/// ~~~ {.cpp}
949/// MyClass *obj = (MyClass*)directory->GetObjectChecked("some object of MyClass","MyClass"));
950/// ~~~
951/// Note: We recommend using the method TDirectory::GetObject:
952/// ~~~ {.cpp}
953/// MyClass *obj = nullptr;
954/// directory->GetObject("some object inheriting from MyClass",obj);
955/// if (obj) { ... we found what we are looking for ... }
956/// ~~~
957
958void *TDirectory::GetObjectChecked(const char *namecycle, const TClass* expectedClass)
959{
960 Short_t cycle;
961 char name[kMaxLen];
962
963 DecodeNameCycle(namecycle, name, cycle, kMaxLen);
964 char *namobj = name;
965 Int_t nch = strlen(name);
966 for (Int_t i = nch-1; i > 0; i--) {
967 if (name[i] == '/') {
968 name[i] = 0;
969 TDirectory* dirToSearch=GetDirectory(name);
970 namobj = name + i + 1;
971 name[i] = '/';
972 if (dirToSearch) {
973 return dirToSearch->GetObjectChecked(namobj, expectedClass);
974 } else {
975 return nullptr;
976 }
977 }
978 }
979
980//*-*---------------------Case of Object in memory---------------------
981// ========================
982 if (!expectedClass || expectedClass->IsTObject()) {
983 TObject *objcur = fList->FindObject(namobj);
984 if (objcur) {
985 if (objcur==this && strlen(namobj)!=0) {
986 // The object has the same name has the directory and
987 // that's what we picked-up! We just need to ignore
988 // it ...
989 objcur = nullptr;
990 } else if (cycle == 9999) {
991 // Check type
992 if (expectedClass && objcur->IsA()->GetBaseClassOffset(expectedClass) == -1) return nullptr;
993 else return objcur;
994 } else {
995 if (objcur->InheritsFrom(TCollection::Class()))
996 objcur->Delete(); // delete also list elements
997 delete objcur;
998 objcur = nullptr;
999 }
1000 }
1001 }
1002
1003 return nullptr;
1004}
1005
1006////////////////////////////////////////////////////////////////////////////////
1007/// Returns the full path of the directory. E.g. `file:/dir1/dir2`.
1008/// The returned path will be re-used by the next call to GetPath().
1009
1010const char *TDirectory::GetPathStatic() const
1011{
1012 static char *path = nullptr;
1013 const int kMAXDEPTH = 128;
1014 const TDirectory *d[kMAXDEPTH];
1015 const TDirectory *cur = this;
1016 int depth = 0, len = 0;
1017
1018 d[depth++] = cur;
1019 len = strlen(cur->GetName()) + 1; // +1 for the /
1020
1021 while (cur->fMother && depth < kMAXDEPTH) {
1022 cur = (TDirectory *)cur->fMother;
1023 d[depth++] = cur;
1024 len += strlen(cur->GetName()) + 1;
1025 }
1026
1027 if (path) delete [] path;
1028 path = new char[len+2];
1029
1030 for (int i = depth-1; i >= 0; i--) {
1031 if (i == depth-1) { // file or TROOT name
1032 strlcpy(path, d[i]->GetName(),len+2);
1033 strlcat(path, ":",len+2);
1034 if (i == 0) strlcat(path, "/",len+2);
1035 } else {
1036 strlcat(path, "/",len+2);
1037 strlcat(path, d[i]->GetName(),len+2);
1038 }
1039 }
1040
1041 return path;
1042}
1043
1044////////////////////////////////////////////////////////////////////////////////
1045/// Returns the full path of the directory. E.g. `file:/dir1/dir2`.
1046/// The returned path will be re-used by the next call to GetPath().
1047
1048const char *TDirectory::GetPath() const
1049{
1051
1052 if (!GetMotherDir()) // case of file
1053 fPathBuffer.Append("/");
1054
1055 return fPathBuffer.Data();
1056}
1057
1058////////////////////////////////////////////////////////////////////////////////
1059/// Recursive method to fill full path for directory.
1060
1062{
1063 TDirectory* mom = GetMotherDir();
1064 if (mom) {
1065 mom->FillFullPath(buf);
1066 buf += "/";
1067 buf += GetName();
1068 } else {
1069 buf = GetName();
1070 buf += ":";
1071 }
1072}
1073
1074////////////////////////////////////////////////////////////////////////////////
1075/// Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
1076///
1077/// Returns 0 in case of error or if a sub-directory (hierarchy) with the requested
1078/// name already exists.
1079/// returnExistingDirectory returns a pointer to an already existing sub-directory with the same name.
1080/// Returns a pointer to the created sub-directory or to the top sub-directory of
1081/// the hierarchy (in the above example, the returned TDirectory * always points
1082/// to "a").
1083/// In particular, the steps to create first a/b/c and then a/b/d without receiving
1084/// errors are:
1085/// ~~~ {.cpp}
1086/// TFile * file = new TFile("afile","RECREATE");
1087/// file->mkdir("a");
1088/// file->cd("a");
1089/// gDirectory->mkdir("b/c");
1090/// gDirectory->cd("b");
1091/// gDirectory->mkdir("d");
1092/// ~~~
1093/// or
1094/// ~~~ {.cpp}
1095/// TFile * file = new TFile("afile","RECREATE");
1096/// file->mkdir("a");
1097/// file->cd("a");
1098/// gDirectory->mkdir("b/c");
1099/// gDirectory->mkdir("b/d", "", true);
1100/// ~~~
1101
1102TDirectory *TDirectory::mkdir(const char *name, const char *title, Bool_t returnExistingDirectory)
1103{
1104 if (returnExistingDirectory) {
1105 auto existingdir = GetDirectory(name);
1106 if (existingdir)
1107 return existingdir;
1108 }
1109 if (!name || !title || !name[0]) return nullptr;
1110 if (!title[0]) title = name;
1111 if (const char *slash = strchr(name,'/')) {
1113 char *workname = new char[size+1];
1114 strncpy(workname, name, size);
1115 workname[size] = 0;
1116 TDirectory *tmpdir;
1117 GetObject(workname,tmpdir);
1118 if (!tmpdir)
1119 tmpdir = mkdir(workname,title);
1120 delete[] workname;
1121 if (!tmpdir) return nullptr;
1122 return tmpdir->mkdir(slash+1);
1123 }
1124
1125 TDirectory::TContext ctxt(this);
1126
1127 return new TDirectory(name, title, "", this);
1128}
1129
1130////////////////////////////////////////////////////////////////////////////////
1131/// List Directory contents.
1132///
1133/// Indentation is used to identify the directory tree
1134/// Subdirectories are listed first, then objects in memory.
1135///
1136/// The option can has the following format:
1137///
1138/// [<regexp>]
1139///
1140/// The `<regexp>` will be used to match the name of the objects.
1141/// By default memory and disk objects are listed.
1142
1144{
1147
1148 TString opta = option;
1149 TString opt = opta.Strip(TString::kBoth);
1150 Bool_t memobj = kTRUE;
1151 TString reg = "*";
1152 if (opt.BeginsWith("-m")) {
1153 if (opt.Length() > 2)
1154 reg = opt(2,opt.Length());
1155 } else if (opt.BeginsWith("-d")) {
1156 memobj = kFALSE;
1157 if (opt.Length() > 2)
1158 reg = opt(2,opt.Length());
1159 } else if (!opt.IsNull())
1160 reg = opt;
1161
1162 TRegexp re(reg, kTRUE);
1163
1164 if (memobj) {
1165 TObject *obj;
1166 TIter nextobj(fList);
1167 while ((obj = (TObject *) nextobj())) {
1168 TString s = obj->GetName();
1169 if (s.Index(re) == kNPOS) continue;
1170 obj->ls(option); //*-* Loop on all the objects in memory
1171 }
1172 }
1174}
1175
1176////////////////////////////////////////////////////////////////////////////////
1177/// Paint all objects in the directory.
1178
1180{
1181 fList->R__FOR_EACH(TObject,Paint)(option);
1182}
1183
1184////////////////////////////////////////////////////////////////////////////////
1185/// Print all objects in the directory.
1186
1188{
1189 fList->R__FOR_EACH(TObject,Print)(option);
1190}
1191
1192////////////////////////////////////////////////////////////////////////////////
1193/// Print the path of the directory.
1194
1196{
1197 Printf("%s", GetPath());
1198}
1199
1200////////////////////////////////////////////////////////////////////////////////
1201/// Recursively remove object from a Directory.
1202
1204{
1205 if (fList)
1206 fList->RecursiveRemove(obj);
1207}
1208
1209////////////////////////////////////////////////////////////////////////////////
1210/// Remove an object from the in-memory list.
1211
1213{
1214 TObject *p = nullptr;
1215 if (fList) {
1216 p = fList->Remove(obj);
1217 }
1218 return p;
1219}
1220
1221////////////////////////////////////////////////////////////////////////////////
1222/// Removes subdirectory from the directory
1223/// When directory is deleted, all keys in all subdirectories will be
1224/// read first and deleted from file (if exists)
1225/// Equivalent call is Delete("name;*");
1226
1227void TDirectory::rmdir(const char *name)
1228{
1229 if ((name==nullptr) || (*name==0)) return;
1230
1231 TString mask(name);
1232 mask+=";*";
1233 Delete(mask);
1234}
1235
1236////////////////////////////////////////////////////////////////////////////////
1237/// Save object in filename,
1238/// if filename is `nullptr` or "", a file with "<objectname>.root" is created.
1239/// The name of the key is the object name.
1240/// By default new file will be created. Using option "a", one can append object
1241/// to the existing ROOT file.
1242/// If the operation is successful, it returns the number of bytes written to the file
1243/// otherwise it returns 0.
1244/// By default a message is printed. Use option "q" to not print the message.
1245/// If filename contains ".json" extension, JSON representation of the object
1246/// will be created and saved in the text file. Such file can be used in
1247/// JavaScript ROOT (https://root.cern/js/) to display object in web browser
1248/// When creating JSON file, option string may contain compression level from 0 to 3 (default 0)
1249
1251{
1252 // option can contain single letter args: "a" for append, "q" for quiet in any combinations
1253
1254 if (!obj) return 0;
1255 Int_t nbytes = 0;
1256 TString fname, opt = option, cmd;
1257 if (filename && *filename)
1258 fname = filename;
1259 else
1260 fname.Form("%s.root", obj->GetName());
1261 opt.ToLower();
1262
1263 if (fname.Index(".json") > 0) {
1264 cmd.Form("TBufferJSON::ExportToFile(\"%s\", (TObject *) 0x%zx, \"%s\");", fname.Data(), (size_t) obj, (option ? option : ""));
1265 nbytes = gROOT->ProcessLine(cmd);
1266 } else {
1267 cmd.Form("TFile::Open(\"%s\",\"%s\");", fname.Data(), opt.Contains("a") ? "update" : "recreate");
1268 TContext ctxt; // The TFile::Open will change the current directory.
1269 TDirectory *local = (TDirectory*)gROOT->ProcessLine(cmd);
1270 if (!local) return 0;
1271 nbytes = obj->Write();
1272 delete local;
1273 }
1274 if (!opt.Contains("q") && !gSystem->AccessPathName(fname.Data()))
1275 obj->Info("SaveAs", "ROOT file %s has been created", fname.Data());
1276 return nbytes;
1277}
1278
1279////////////////////////////////////////////////////////////////////////////////
1280/// Set the name for directory
1281/// If the directory name is changed after the directory was written once,
1282/// ROOT currently would NOT change the name of correspondent key in the
1283/// mother directory.
1284/// DO NOT use this method to 'rename a directory'.
1285/// Renaming a directory is currently NOT supported.
1286
1287void TDirectory::SetName(const char* newname)
1288{
1289 TNamed::SetName(newname);
1290}
1291
1292////////////////////////////////////////////////////////////////////////////////
1293/// Decode a namecycle "aap;2" into name "aap" and cycle "2". Destination
1294/// buffer size for name (including string terminator) should be specified in
1295/// namesize.
1296/// @note Edge cases:
1297/// - If the number after the `;` is larger than `SHORT_MAX`, cycle is set to `0`.
1298/// - If name ends with `;*`, cycle is set to 10000`.
1299/// - In all other cases, i.e. when number is not a digit or buffer is a nullptr, cycle is set to `9999`.
1300
1301void TDirectory::DecodeNameCycle(const char *buffer, char *name, Short_t &cycle,
1302 const size_t namesize)
1303{
1304 if (!buffer) {
1305 cycle = 9999;
1306 return;
1307 }
1308
1309 size_t len = 0;
1310 const char *ni = strchr(buffer, ';');
1311
1312 if (ni) {
1313 // Found ';'
1314 len = ni - buffer;
1315 ++ni;
1316 } else {
1317 // No ';' found
1318 len = strlen(buffer);
1319 ni = &buffer[len];
1320 }
1321
1322 if (namesize) {
1323 if (len > namesize-1ul) len = namesize-1; // accommodate string terminator
1324 } else {
1325 ::Warning("TDirectory::DecodeNameCycle",
1326 "Using unsafe version: invoke this method by specifying the buffer size");
1327 }
1328
1329 strncpy(name, buffer, len);
1330 name[len] = '\0';
1331
1332 if (*ni == '*')
1333 cycle = 10000;
1334 else if (isdigit(*ni)) {
1335 long parsed = strtol(ni,nullptr,10);
1336 if (parsed >= (long) std::numeric_limits<Short_t>::max())
1337 cycle = 0;
1338 else
1339 cycle = (Short_t)parsed;
1340 } else
1341 cycle = 9999;
1342}
1343
1345{
1346 // peg the current directory
1347 TDirectory *current;
1348 {
1350 current = TDirectory::CurrentDirectory().load();
1351 // Don't peg if there is no current directory or if the current
1352 // directory's destruction has already started (in another thread)
1353 // and is waiting for this thread to leave the critical section.
1354 if (!current || !current->IsBuilt())
1355 return;
1356 ++(current->fContextPeg);
1357 }
1358 current->RegisterContext(this);
1359 --(current->fContextPeg);
1360}
1361
1362///////////////////////////////////////////////////////////////////////////////
1363/// Register a TContext pointing to this TDirectory object
1364
1367
1368 if (!IsBuilt() || this == ROOT::Internal::gROOTLocal)
1369 return;
1370 if (fContext) {
1371 TContext *current = fContext;
1372 while(current->fNext) {
1373 current = current->fNext;
1374 }
1375 current->fNext = ctxt;
1376 ctxt->fPrevious = current;
1377 } else {
1378 fContext = ctxt;
1379 }
1380}
1381
1382////////////////////////////////////////////////////////////////////////////////
1383/// Register a std::atomic<TDirectory*> that will soon be pointing to this TDirectory object
1384
1386{
1388 if (std::find(fGDirectories.begin(), fGDirectories.end(), gdirectory_ptr) == fGDirectories.end()) {
1389 fGDirectories.emplace_back(gdirectory_ptr);
1390 }
1391 // FIXME:
1392 // globalptr->load()->fGDirectories will still contain globalptr, but we cannot
1393 // know whether globalptr->load() has been deleted by another thread in the meantime.
1394}
1395
1396
1397////////////////////////////////////////////////////////////////////////////////
1398/// \copydoc TDirectory::WriteObject(const T*,const char*,Option_t*,Int_t).
1399
1400Int_t TDirectory::WriteTObject(const TObject *obj, const char *name, Option_t * /*option*/, Int_t /*bufsize*/)
1401{
1402 const char *objname = "no name specified";
1403 if (name) objname = name;
1404 else if (obj) objname = obj->GetName();
1405 Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.",GetName(),objname);
1406 return 0;
1407}
1408
1409////////////////////////////////////////////////////////////////////////////////
1410/// UnRegister a TContext pointing to this TDirectory object
1411
1413
1415
1416 // Another thread already unregistered the TContext.
1417 if (ctxt->fDirectory == nullptr || ctxt->fDirectory == ROOT::Internal::gROOTLocal)
1418 return;
1419
1420 if (ctxt==fContext) {
1421 fContext = ctxt->fNext;
1422 if (fContext) fContext->fPrevious = nullptr;
1423 ctxt->fPrevious = ctxt->fNext = nullptr;
1424 } else {
1425 TContext *next = ctxt->fNext;
1426 ctxt->fPrevious->fNext = next;
1427 if (next) next->fPrevious = ctxt->fPrevious;
1428 ctxt->fPrevious = ctxt->fNext = nullptr;
1429 }
1430}
1431
1432////////////////////////////////////////////////////////////////////////////////
1433/// TDirectory Streamer.
1435{
1436 // Stream an object of class TDirectory.
1437
1438 UInt_t R__s, R__c;
1439 if (R__b.IsReading()) {
1440 Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
1441 TNamed::Streamer(R__b);
1442 R__b >> fMother;
1443 R__b >> fList;
1444 fList->UseRWLock();
1445 fUUID.Streamer(R__b);
1446 R__b.CheckByteCount(R__s, R__c, TDirectory::IsA());
1447 } else {
1448 R__c = R__b.WriteVersion(TDirectory::IsA(), kTRUE);
1449 TNamed::Streamer(R__b);
1450 R__b << fMother;
1451 R__b << fList;
1452 fUUID.Streamer(R__b);
1453 R__b.SetByteCount(R__c, kTRUE);
1454 }
1455}
#define SafeDelete(p)
Definition RConfig.hxx:550
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
long Long_t
Definition RtypesCore.h:54
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:124
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
void(* tcling_callfunc_Wrapper_t)(void *, int, void **, void *)
static std::atomic_flag * GetCurrentDirectoryLock()
static TBuffer * R__CreateBuffer()
Fast execution of 'new TBufferFile(TBuffer::kWrite,10000), without having a compile time circular dep...
const Int_t kMaxLen
#define gDirectory
Definition TDirectory.h:384
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void reg
char name[80]
Definition TGX11.cxx:110
Int_t gDebug
Definition TROOT.cxx:595
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
#define R__LOCKGUARD(mutex)
A spin mutex-as-code-guard class.
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr)=0
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
@ kWrite
Definition TBuffer.h:73
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
Bool_t IsReading() const
Definition TBuffer.h:86
virtual void ResetMap()=0
void SetBufferOffset(Int_t offset=0)
Definition TBuffer.h:93
void SetReadMode()
Set buffer in read mode.
Definition TBuffer.cxx:302
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual void MapObject(const TObject *obj, UInt_t offset=1)=0
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:4978
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition TClass.cxx:7487
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:5938
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4874
Int_t GetBaseClassOffset(const TClass *toBase, void *address=nullptr, bool isDerivedObject=true)
Definition TClass.cxx:2791
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2968
static TClass * Class()
virtual bool UseRWLock(Bool_t enable=true)
Set this collection to use a RW lock upon access, making it thread safe.
R__ALWAYS_INLINE Bool_t IsUsingRWLock() const
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
std::atomic< bool > fDirectoryWait
Set to true during the destructor execution.
Definition TDirectory.h:93
void CdNull()
Set the current directory to null.
~TContext()
Destructor.
TContext * fPrevious
Set to true if a TDirectory might still access this object.
Definition TDirectory.h:94
TContext * fNext
Pointer to the next TContext in the implied list of context pointing to fPrevious.
Definition TDirectory.h:95
std::atomic< TDirectory * > fDirectory
Definition TDirectory.h:91
Describe directory structure in memory.
Definition TDirectory.h:45
std::shared_ptr< std::atomic< TDirectory * > > SharedGDirectory_t
Pointer to a list of TContext object pointing to this TDirectory.
Definition TDirectory.h:147
Bool_t cd1(const char *path)
flag to add histograms, graphs,etc to the directory
static TClass * Class()
void Delete(const char *namecycle="") override
Delete Objects or/and keys in a directory.
virtual void Close(Option_t *option="")
Delete all objects from memory and directory structure itself.
virtual void Save()
Definition TDirectory.h:253
virtual TList * GetList() const
Definition TDirectory.h:222
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
virtual const char * GetPath() const
Returns the full path of the directory.
std::atomic_flag fSpinLock
Counter delaying the TDirectory destructor from finishing.
Definition TDirectory.h:154
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
virtual void * GetObjectUnchecked(const char *namecycle)
Return pointer to object identified by namecycle.
void Draw(Option_t *option="") override
Fill Graphics Structure and Paint.
virtual void DeleteAll(Option_t *option="")
Delete all objects from memory.
std::atomic< size_t > fContextPeg
thread local gDirectory pointing to this object.
Definition TDirectory.h:153
std::vector< SharedGDirectory_t > fGDirectories
Definition TDirectory.h:151
virtual void rmdir(const char *name)
Removes subdirectory from the directory When directory is deleted, all keys in all subdirectories wil...
static Bool_t AddDirectoryStatus()
Static function: see TDirectory::AddDirectory for more comments.
void FillFullPath(TString &buf) const
Recursive method to fill full path for directory.
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add objects like histograms, TGraph2D, etc in memory.
void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.).
void ls(Option_t *option="") const override
List Directory contents.
TContext * fContext
Buffer for GetPath() function.
Definition TDirectory.h:145
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
void RegisterGDirectory(SharedGDirectory_t &ptr)
Register a std::atomic<TDirectory*> that will soon be pointing to this TDirectory object.
TDirectory()
Directory default constructor.
static void DecodeNameCycle(const char *namecycle, char *name, Short_t &cycle, const size_t namesize=0)
Decode a namecycle "aap;2" into name "aap" and cycle "2".
static Bool_t Cd(const char *path)
Change current directory to "path".
void Clear(Option_t *option="") override
Delete all objects from a Directory list.
virtual Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *="", Int_t=0)
Write an object with proper type checking.
virtual TFile * GetFile() const
Definition TDirectory.h:220
TObject * FindObject(const char *name) const override
Find object by name in the list of memory objects.
void Print(Option_t *option="") const override
Print all objects in the directory.
virtual Bool_t cd()
Change current directory to "this" directory.
virtual ~TDirectory()
Destructor.
static Bool_t Cd1(const char *path)
Change current directory to "path".
void UnregisterContext(TContext *ctxt)
UnRegister a TContext pointing to this TDirectory object.
void Streamer(TBuffer &) override
TDirectory Streamer.
void RecursiveRemove(TObject *obj) override
Recursively remove object from a Directory.
virtual Int_t SaveObjectAs(const TObject *, const char *="", Option_t *="") const
Save object in filename, if filename is nullptr or "", a file with "<objectname>.root" is created.
TString fPathBuffer
Definition TDirectory.h:144
virtual TDirectory * mkdir(const char *name, const char *title="", Bool_t returnExistingDirectory=kFALSE)
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
void SetName(const char *newname) override
Set the name for directory If the directory name is changed after the directory was written once,...
void BuildDirectory(TFile *motherFile, TDirectory *motherDir)
Initialise directory to defaults.
static SharedGDirectory_t & GetSharedLocalCurrentDirectory()
Return the (address of) a shared pointer to the struct holding the actual thread local gDirectory poi...
TUUID fUUID
Definition TDirectory.h:143
static Bool_t fgAddDirectory
MSVC doesn't support = ATOMIC_FLAG_INIT;.
Definition TDirectory.h:156
TDirectory * GetMotherDir() const
Definition TDirectory.h:225
virtual const char * GetPathStatic() const
Returns the full path of the directory.
static std::atomic< TDirectory * > & CurrentDirectory()
Return the current directory for the current thread.
TClass * IsA() const override
Definition TDirectory.h:308
TObject * fMother
Definition TDirectory.h:141
void Browse(TBrowser *b) override
Browse the content of the directory.
void GetObject(const char *namecycle, T *&ptr)
Get an object with proper type checking.
Definition TDirectory.h:212
virtual void pwd() const
Print the path of the directory.
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl)
virtual TObject * CloneObject(const TObject *obj, Bool_t autoadd=kTRUE)
Clone an object.
Bool_t IsBuilt() const
Definition TDirectory.h:234
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
void RegisterContext(TContext *ctxt)
Register a TContext pointing to this TDirectory object.
TList * fList
Definition TDirectory.h:142
void Paint(Option_t *option="") override
Paint all objects in the directory.
virtual TObject * FindObjectAny(const char *name) const
Find object by name in the list of memory objects of the current directory or its sub-directories.
A ROOT file is composed of a header, followed by consecutive data records (TKey instances) with a wel...
Definition TFile.h:53
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition THashList.h:34
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:402
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:578
void RecursiveRemove(TObject *obj) override
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition TList.cxx:764
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:822
virtual TObjLink * FirstLink() const
Definition TList.h:102
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
void Streamer(TBuffer &) override
Stream an object of class TObject.
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:140
TClass * IsA() const override
Definition TNamed.h:58
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:888
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:962
static TClass * Class()
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition TObject.cxx:880
virtual void Delete(Option_t *option="")
Delete this object.
Definition TObject.cxx:248
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:976
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1004
virtual TClass * IsA() const
Definition TObject.h:245
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition TObject.cxx:574
void ResetBit(UInt_t f)
Definition TObject.h:200
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:62
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition TObject.h:65
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:64
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:950
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:2825
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2833
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2707
Regular expression class.
Definition TRegexp.h:31
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:419
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
const char * Data() const
Definition TString.h:378
@ kBoth
Definition TString.h:278
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:625
Bool_t IsNull() const
Definition TString.h:416
TString & Append(const char *cs)
Definition TString.h:574
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:634
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:653
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1284
virtual void Streamer(TBuffer &)
R__EXTERN TROOT * gROOTLocal
Definition TROOT.h:379
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition Rtypes.h:114
@ kExactMatch
TCanvas * slash()
Definition slash.C:1
th1 Draw()
TMarker m
Definition textangle.C:8