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