Re: [ROOT] Concurrent access to multiple TFiles and gDirectory

From: Rene Brun (Rene.Brun@cern.ch)
Date: Wed Jan 28 2004 - 14:34:28 MET


Hi Brandon,

The current implementation is not thread safe in case two concurrent threads try
to write in the same file. We are planning to support this possibility
in changing the global pointers gFile and gDirectory using the same trick
that we use for gPad (which is thread safe).

Now, your problem is different. You have ONE writer and multiple readers.
The current implementation is OK for this. In attachement, I join an example
explaining how to do it.
If you use TTreeViewer, we introduced recently (3.10/02) a Refresh
button that automatically refresh the directory on the reader side.

Rene Brun

Brandon Kohn wrote:
> 
> Hello Rooters,
> 
> I was wondering if anyone here had any experience with using TFiles in a
> multi-threaded application or if this is even possible given the current use
> of the global gDirectory. I'm interested in implementing a single
> application that will contain one thread writing to a TFile, whilst allowing
> another to serve data (from a different TFile) for browsing by users. My
> understanding of the current IO system's implementation would seem to
> require that all file accesses would have to be atomic at the level of the
> calls to root.
> 
> The first problem that I see with this, is that such locking would likely
> remove much of the benefit of multithreading because the blocking mechanism
> wouldn't release the locks during the actual system level IO (which is
> exactly where you're likely to see some performance improvements.)
> 
> Does anyone have some information about using ROOT in this way?
> 
> Thanks for any help...
> 
> Brandon
> ____________________________________________________________
> Brandon Kohn                        Tel.: +377 97 97 41 51
> Software Engineer/Sys Admin
> The Maia Institute                   Fax.: +377 97 97 41 59
> Le Patio Palace
> ____________________________________________
> 
> Important Notice
> 
> This email and any attachments to it are confidential and intended solely
> for the individual(s) to whom they are addressed.  Any modification or
> dissemination of the contents of this e-mail is strictly prohibited unless
> expressly authorised by the sender.  If you receive this e-mail by mistake,
> please advise the sender immediately by using the reply facility in your
> e-mail software.  Please also delete the message from your computer, and
> destroy any paper copies. Thank you for your co-operation.

void fw() {
//  example showing how to save objects to a file such that they
// can be read in parallel by another Root session.
// Every kUPDATE entries, the current histograms and ntuple
// are written to the file replacing the previous objects
//
// In a different Root session, one can look at the objects without
// reopening the file. See for example macro fr.C
//
//   void fr() {
//   if (gROOT->GetListOfFiles()->FindObject("hsi.root")) {
//      gDirectory->ReadKeys();
//   } else {
//      TFile *file = new TFile("hsi.root");
//   }
//   TNtuple *ntuple = (TNtuple*)gDirectory->Get("ntuple");
//   printf("ntuple has now %d entries\n",ntuple->GetEntries());
//   delete ntuple;
//}
//
// To test this facility, do:
// process1, run root
//       root > .x fw.C
// process2, run a new version of root
//       root > .x fr.C
//       root > .x fr.C, etc
   
  TFile *hfile = new TFile("hsi.root","RECREATE");

// Create some histograms, a profile histogram and an ntuple
  hpx    = new TH1F("hpx","This is the px distribution",100,-4,4);
  hpxpy  = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4);
  hprof  = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
  ntuple = new TNtuple("ntuple","Demo ntuple","px:py:pz:random:i");

// Fill histograms randomly
  gRandom->SetSeed();
  Float_t px, py, pz;
  const Int_t kUPDATE = 10000;
  Int_t mode;
  for (Int_t i = 0; i < 2500000; i++) {
     gRandom->Rannor(px,py);
     pz = px*px + py*py;
     Float_t random = gRandom->Rndm(1);
     hpx->Fill(px);
     hpxpy->Fill(px,py);
     hprof->Fill(px,pz);
     ntuple->Fill(px,py,pz,random,i);
     if (i && (i%kUPDATE) == 0) {
        mode = TObject::kOverwrite;
        hpx->Write(0,mode);
        hpxpy->Write(0,mode);
        hprof->Write(0,mode);
        ntuple->Write(0,mode);
        hfile->SaveSelf(); //this is the key statement
     }
  }
  hfile->Write();
}



This archive was generated by hypermail 2b29 : Sun Jan 02 2005 - 05:50:05 MET