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