Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:47:50

0001 #include "TFile.h"
0002 #include "TTree.h"
0003 #include "TBranch.h"
0004 #include "TClass.h"
0005 #include "TThread.h"
0006 #include "TVirtualStreamerInfo.h"
0007 #include "TList.h"
0008 #include "TMap.h"
0009 #include "TObjString.h"
0010 #include "TH1F.h"
0011 
0012 
0013 #include <memory>
0014 #include <cassert>
0015 #include <iostream>
0016 #include <thread>
0017 #include <atomic>
0018 #include <sstream>
0019 
0020 std::atomic<bool> waitToStart{true};
0021 std::atomic<unsigned int> countdownToWrite{0};
0022 
0023 void printHelp(const char* iName, int iDefaultNThreads)
0024 {
0025   std::cout << iName <<" [number of threads] [gDebug value]\n\n"
0026             <<"[number of threads] number of threads to use in test\n"
0027             <<"[gDebug value] value of gDebug to pass to ROOT (gDebug=1 is useful)\n"
0028             <<"If no arguments are given "<<iDefaultNThreads<<" threads will be used"<<std::endl;
0029 }
0030 
0031 std::pair<int,int> parseOptionsForNumberOfThreadsAndgDebug(int argc, char** argv)
0032 {
0033   constexpr int kDefaultNThreads = 4;
0034   int kDefaultgDebug = gDebug;
0035   int nThreads = kDefaultNThreads;
0036   int newGDebug = kDefaultgDebug;
0037   if( argc >= 2 ) {
0038     if(strcmp("-h",argv[1]) ==0) {
0039       printHelp(argv[0],kDefaultNThreads);
0040       exit( 0 );
0041     }
0042     
0043     nThreads = atoi(argv[1]);
0044   }
0045   if(argc == 3) {
0046     newGDebug = atoi(argv[2]);
0047   }
0048   
0049   if( argc > 3) {
0050     printHelp(argv[0],kDefaultNThreads);
0051     exit(1);
0052   }
0053   return std::make_pair(nThreads, newGDebug) ;
0054 }
0055 
0056 TList* createList() {
0057   auto returnValue = new TList();
0058 
0059   for(unsigned int i=0; i<10;++i) {
0060     returnValue->Add(new TList());
0061     returnValue->Add(new TMap());
0062     returnValue->Add(new TObjString());
0063     returnValue->Add(new TH1F());
0064     returnValue->Add(new TH1D());
0065   }
0066 
0067   return returnValue;
0068 }
0069 
0070 int main(int argc, char** argv) {
0071 
0072   auto values = parseOptionsForNumberOfThreadsAndgDebug(argc,argv);
0073 
0074   const int kNThreads = values.first;
0075   countdownToWrite = kNThreads;
0076 
0077   gDebug = values.second;
0078 
0079   //Tell Root we want to be multi-threaded
0080   TThread::Initialize();
0081   //When threading, also have to keep ROOT from logging all TObjects into a list
0082   TObject::SetObjectStat(false);
0083   //Have to avoid having Streamers modify themselves after they have been used
0084   TVirtualStreamerInfo::Optimize(false);
0085 
0086 
0087 
0088   std::vector<std::shared_ptr<std::thread>> threads;
0089   threads.reserve(kNThreads);
0090 
0091   
0092 
0093   for(int i=0; i< kNThreads; ++i) {
0094     threads.push_back(std::make_shared<std::thread>( std::thread([i]() {
0095     static thread_local TThread s_thread_guard;
0096 
0097         std::stringstream nameStream;
0098         nameStream <<"write_thread_"<<i<<".root";
0099 
0100         auto theList = createList();
0101 
0102     while(waitToStart) ;
0103     TFile f(nameStream.str().c_str(), "RECREATE","test");
0104         
0105         auto listTree = new TTree("TheList","TheList");
0106     listTree->Branch("theList","TList",&theList);
0107 
0108         --countdownToWrite;
0109         while(countdownToWrite !=0) ;
0110 
0111     for(unsigned int i = 0; i<100;++i) {
0112       listTree->Fill();
0113     }
0114     f.Write();
0115     f.Close();
0116       }) ) );
0117       
0118   }      
0119   waitToStart = false;
0120   for(auto& t : threads) {
0121     t->join();
0122   }
0123 
0124   return 0;
0125 }
0126