Storage Ownserhip

I’m trying to slide bits and pieces of Root under the hood of another data analysis program. It would be really useful to be able to manage ‘storage ownership’ For example, I create a TH1I. I can use Adopt or directly set fArray to point its storage wherever I want. In my case, the storage is being pointed to a chunk of shared memory from which the program’s legacy presenter accesses the spectrum bulk storage for display.
What I’d like, therefore, is to be able tot ell TH1I (well Really TArrayI) that I’m managing the storage and that therefore it should not delete it on destruction.
I can do the dance needed when the program runs, but if I invoke gApplication->Terminate(0), Root runs around destroying my histograms (fine) and their underlying storage (not so fine).

That’s why we are redesigning the histograms. If you look at ROOT::Experimental::TH1I https://root.cern.ch/doc/master/classROOT_1_1Experimental_1_1THist.html you’ll see that

  • it separates bin finding from storage
  • it trusts you on ownership.

Maybe try those? I’m aware that functionality is nowhere close to ::TH1I - but tell us what you’re missing and it shall be implemented :slight_smile:

Axel,
Thank you for your quick reply but I’m not certain I understand from the pointer to the docs how to use this. Can you supply a simple example for how I’d manage storage of such an object?

Thanks,
Ron

Hi Ron,

Do you ever fill the histogram or is this just a question of visualizing “its” data?

Axel.

Let me say in some detail the application that I’ve got. I have a legacy application that does histogramming. I am sliding bits and pieces of root underneath its hood with the eventual goal that the guts of the application will, at some time be entirely root.
The histogramming part of the system has classes that all derive from a base class (CSpectrum). CSpectrum has construtors and virtual methods that, given an event increment the spectrum. The contents (channels) of a histogram can be moved into a shared memory region from which another, legacy, displayer can do visualization.
What I’ve done so far:

  • I’ve made the event loop of my application call the root event loop so that root GUI objects can be live.
  • I’ve added the ability for my application to pass a root macro file name to root for execution.
  • For the spectrum base class I’ve essentially done something like this (here’s where I want storage management - pardon the difference in coding conventions):

CSpectrum {
private:
   TH1* m_pRootHistogram;
...
   void setRootHistogram(TH1* pH) {
      m_pRootHistogram = pH;
   }
   void getRootHistogram() { return  m_pRootHistogram; }

Derived classes, for example a 1 D long spectrum might construct with code a bit like:

TH1I* pRootHistogram = new TH1I(....);
pRootHistogram->Adopt(0, nullptr);           // deletes original storage
pRootHistogram->fArray = createStorage(); // Use my managed storage.
setRootHistogram(m_pRootHistogram);

Destruction for such a class now looks like:
Each spectrum type implements a member setStorage which is used when my application relocates a histogram in or out of display memory. That method will just set the fArray member of the root histogram’s TArray as above

TH1I* pH = reinterpret_cast<TH1I*>(getRootHistogram();
pH->fArray = nullptr;

The virtual Increment method each of my histograms produces now just does a Fill on the underlying root histogram.
What I’m able to do now is view the histogram in both my legacy displayer and by running root macros (e.g. instantiating a TBrowser and double clicking the histogram). Sure enough I see the same data in both viewers.

The problems arise around edges. For example. On program exit, Root will attempt to clean up the in memory histograms and that will include deleting the fArray storage which will, in general cause a free error to be tossed, because fArray’s storage won’t be on the heap if its in display memory.

Much of these I’ve worked around with some degree of simplicity or complexity – most of the time – but it would have been nice to be able to tell the TArray used by TH1I that I’m managing its storage so that it’s destructor won’t delete it.

Ideally, if TH1I had encapsulated rather than inherited TArrayI, I could deal with this more cleanly by deriving from TArrayI and replacing the member data, but TH1I inherits and therefore that’s not an option.

Hopefully this is not so confusing.