TROOT and threads,

From: Tomasz Bold <Tomasz.Bold_at_cern.ch>
Date: Tue, 16 Aug 2005 19:08:26 +0200


Dera ROOTers,

        Is it possible to have multiple TROOT instances in every thread? The problem is that the usage of gDirectory common for all the threads screws up the navigation which uses it.

The feature I expect is to have separate TROOT in each thrad. I tried to do as follows:
void runit(int *tid)
{

   ostringstream rname;
   rname << "r" << pthread_self() << ends;

   TROOT r(rname.str().c_str(), "R");
   gROOT = &r;
   gDirectory = gROOT;         

        and later as usually bookking and writing but it crashed.

Is this the recomended method of using ROOT in multithread environment or it is better to secure each file operation by mutex.

I attached the code example.

Regards,

        Tomasz Bold

// the code here tests ROOT histogramng in threads,
// Each thread (out of 3) is running the same code which books/fills/and saves 
// the histograms.
//
// to compile
// 
// g++ roottest.cpp -o roottest `root-config --cflags` `root-config --libs`
//

#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>
#include <cmath>
#include <TH1F.h>
#include <TFile.h>

#include <sstream>

const int SINGLEFILE = 1;

using namespace std;
pthread_mutex_t m_writemutex = PTHREAD_MUTEX_INITIALIZER;

void runit(int *tid)
{

  ostringstream rname;
  rname << "r" << pthread_self() << ends;

  TROOT r(rname.str().c_str(), "R");   gROOT = &r;
  gDirectory = gROOT;

  cerr << "gROOT " << gROOT << endl;

  int id = *tid;

  TH1F h0("h0", "h0 test" , 100, 0, 100);

  TH1F h1("h1", "h1 test" , 10, 0, 10);

  // fill them
  // the content should not matter

  for ( int i = 0 ; i < 1000 ; i++ ){
    h0.Fill (float(id*(i%100)));
    h1.Fill (id);
  }
  // cout << "h0 entries " << h0.GetEntries() << endl;   usleep (random() & 0xfff);   

  // pthread_mutex_lock(&m_writemutex);

  TString name;
  TString mode;
  // save the histograms
  if ( SINGLEFILE )
    {

      mode = "UPDATE";
      name = "test-one.root";
      cout << name << " from thread of ID  " << id << endl;
    }
  else
    {
      mode = "RECREATE";
      name = Form("test%d.root", id);

      cout << name << " from thread of ID  " << id << endl;
    }

  // open the file
  TFile fi(name.Data(), mode.Data());

  // will change name for the first
  name.Resize(0);
  name = h0.GetName();
  name += id;
  fi.WriteTObject(&h0, name.Data());

  // Will keep the name (ROOT will add cycles)   name.Resize(0);
  name = h1.GetName();
  fi.WriteTObject(&h1, name.Data());   

  fi.Write();
  fi.Close();
  // pthread_mutex_unlock(&m_writemutex); }

int main()
{
  int id0 = 0;   

  runit(&id0);
  int id1=1, id2=2, id3=3;
  pthread_t t1, t2, t3;   

  void *ret;
  // create threads and start the tasks

  pthread_create ( &t1, 0, (void*(*)(void*))runit, &id1);
  pthread_create ( &t2, 0, (void*(*)(void*))runit, &id2);
  pthread_create ( &t3, 0, (void*(*)(void*))runit, &id3);
  

  // wait for the workers

  pthread_join (t1, &ret);
  pthread_join (t2, &ret);
  pthread_join (t3, &ret);
  

  pthread_mutex_destroy(&m_writemutex);
} Received on Tue Aug 16 2005 - 19:04:38 MEST

This archive was generated by hypermail 2.2.0 : Tue Jan 02 2007 - 14:45:11 MET