@pcanal : I determined the cause of the segfault was calling Draw()
on the TH1I
pointer that was still NULL
.
I realize now my issue with
delete file->FindObject(name);
file->ReadKeys();
These commands only work if you have loaded the ROOT file that is actively being written. This does not work if you have opened an old file of the same name. When the file is RECREATE
d,
I now have two working methods of reading a file from disk while a process is actively writing to it. Below I post both the example, and steps to run. I will mark the topic as solved.
Working Example
///@file example-28273.C
///@brief A program that will generate data and asynchronously write it to disk.
///@author S. V. Paulauskas
///@date March 12, 2018
///@copyright Copyright (c) 2018 S. V. Paulauskas.
///@copyright All rights reserved. Released under the Creative Commons Attribution-ShareAlike 4.0 International License
#include <TFile.h>
#include <TH1D.h>
#include <iostream>
#include <mutex>
#include <thread>
void AsyncFlush(TFile *file, std::mutex *lock, unsigned int *loopId) {
std::cout << "AsyncFlush - Now calling file->Write" << std::endl;
file->Write(0, TObject::kWriteDelete);
std::cout << "AsyncFlush - Now unlocking the file for writing in loop " << *loopId << std::endl;
lock->unlock();
}
void WriteToDisk(TFile *file, unsigned int *loopID, std::mutex *lock) {
if (lock->try_lock()) {
std::cout << "WriteToDisk - we're creating the new thread in loop number " << *loopID << endl;
std::thread worker0(AsyncFlush, file, lock, loopID);
worker0.detach();
}
}
void GenerateHistogram() {
std::mutex lock;
TFile *f = new TFile("test.root", "RECREATE");
TH1D *hist = new TH1D("hist", "", 100, -2, 2);
unsigned int loopCounter = 0;
while (loopCounter < 40000) {
hist->FillRandom("gaus", 10000);
WriteToDisk(f, &loopCounter, &lock);
loopCounter++;
}
while(!lock.try_lock())
sleep(1);
f->Write(nullptr, TObject::kWriteDelete);
f->Close();
}
// Adapted from
// https://root-forum.cern.ch/t/read-a-tfile-while-writing-with-another-process/18608/6
// and follow up comment
// https://root-forum.cern.ch/t/read-histogram-tree-from-tfile-while-actively-writing-to-it/28273/10
void ReadHistogram(TFile *file, const char *name = "hist") {
TH1D *hist1 = nullptr;
delete file->FindObject(name);
file->ReadKeys();
file->GetObject(name, hist1);
if(hist1)
hist1->Draw();
}
// Adapted from
// https://root-forum.cern.ch/t/read-a-tfile-while-writing-with-another-process/18608/7
void ReadHistogram() {
TFile *file = TFile::Open("test.root");
TH1D *hist = nullptr;
file->GetObject("hist", hist);
if(hist)
hist->Draw();
}
Instructions for Running Script
Terminal A - The Writer
user@localhost:> root
root [0] .L example.C+;
root [1] GenerateHistogram();
Terminal B - The Reader
user@localhost:> root
root [0] .L example_C.so;
root [1] ReadHistogram();
root [2] ReadHistogram();
root [3] ReadHistogram();
...
Terminal C - The Reader (alternate)
Executed after Writing has started in Terminal A
user@localhost:> root test.root
root [0] .L example_C.so;
root [1] ReadHistogram(_file0);
root [2] ReadHistogram(_file0);
root [3] ReadHistogram(_file0);
...