Difference between win32 and win32gdk versions of root

Hello,
I have a dll that I built with root libaries that does not do any graphics, just crunches numbers. When I migrated from win32 version 3.05/5 to win32gdk version 3.05/7, I noticed that my application that calls the gdk based dll used up 100% of the cpu time while the win32 based dll used only about 10%. I found that if I instantiate TApplication() in the dll, than the gdk based dll stops hogging all the cpu (and the win32 based still works fine) This might be relevant to what follows, maybe not…

My question is, does TApplication create a new thread in the GDK version? I am now finding some pecular behavior in my gdk based dll when it is called by different threads. My application has one thread A and many thread B’s: Here’s what happens:

Thread A does the following

  1. call dll method that instantiates TApplication
  2. call dll method that creates a bunch of user objects
  3. start thread B
  4. Wait for B to terminate
  5. Get info from objects and delete user objects
  6. Go to 2

Thread B writes TTrees (TTrees and TFiles created in 2 above), fills histograms (booked in 2 above), occasionaly fits a histogram and occasionally AutoSaves() the TTrees and writes the objects. When its done, the thread terminates.

The problem I get is occasionally at step 5 above, some portion of some object appears corrupted and I get an access violation (a typical place that this happens is when TGraph::GetFunction() is called. Following the traceback, the crash is always in TList::FindObject() - one of the obj’s in the list is corrupted. Note: my dll has a TGraph object in it, but I never draw it - there’s no canvas even)

It almost seems like Thread B terminates before something within root is really finished - this is why I pose the question.

Thanks…
Ed Oltman

Ed,

Could you run your test with the version 3.10/00 ?

Rene

I forgot to mention, I am running with win32gdk version built from

ftp://root.cern.ch/root/root_v3.10.00.source.tar.gz

dated Saturday, September 20, 2003, 8:12 AM. I run on Window 2000 and compile with visual c++ 6.0 w/ sp5

Hi Ed,
I’m very interesing to look at your program.

[quote=“eoltman”]Hello,
I have a dll that I built with root libaries that does not do any graphics, just crunches numbers. When I migrated from win32 version 3.05/5 to win32gdk version 3.05/7, I noticed that my application that calls the gdk based dll used up 100% of the cpu time while the win32 based dll used only about 10%. I found that if I instantiate TApplication() in the dll, than the gdk based dll stops hogging all the cpu (and the win32 based still works fine) This might be relevant to what follows, maybe not…
[/quote]

I believed that problem with 100% CPU time wasting when TApplication
is not instantiated was solved. Let me look at your program.

ROOT win32gdk has 3 threads:

  • one driving event loop (TApplication::Run)
  • one handling console input
  • one handling GUI events (like X-server). Any TVirtualX call is
    translated to PostThreadMessage to this thread.

Sharing objects between threads without locking woud be
dangeraous. I have experimental version of win32gdk with
built-in objects locking. Let me look at your code.

Thanks. Regards. Valeriy

Valeriy,
Its a bit impractical to show you the code as its rather large with many files and dependancies. The root based dll itself is somewhat large - 10s of files. The application that calls it is a much larger system that has too many h/w and s/w dependancies to reproduce. What I could do is provide some pseudo code that describes the root specific things that thread A and B do…

So, it sounds like I no longer need to instantiate TApplication() (I added that back in 3.05/7 - now I’m using 3.10/0) - I will try that.

Given that there is no console input (e.g. I used TApplication, not TRint) and there is no GUI involved, are there still 3 threads involved?

Back to the (overly complex) program that uses my dll: Step 4 of Thread A insures that when thread B is running, thread A is sleeping and when thread A is running, thread B does’nt exist. Thus, there appears to be no need for locking since there is never a situatiuon when both threads are execting at the same time.

However, Is it possible that thread B calls a root function who’s work is carried out in root thread R? If this happens, B could terminate before R is finished and A and R might collide. Does this make sense?

Thanks for you attention!

Ed

I have found a solution to my problem! It is not a win32gdk vs. win32 difference - its just the problem that never manifested in win32, but occasionally did in win32gdk. Do the following two snippets look like the wrong way and the right way to change the TF1 associated with a TGraph? (or perhaps they are both wrong…)
TGraph *fGraph has TF1 function named “calibFunc” associated with it. After reading in fGraph from a root file, I changed the associated function by doing the following:

  // This appears to be wrong, but I don't know why...
  TF1 *f = fGraph->GetFunction("calibFunc")
  delete f;
  f = new TF1("calibFunc"...)
  f->SetParameters(...)

This worked fine with the win32 code, but occasionally caused problems in the win32gdk code when I would attempt fGraph->GetFunction(“calibFunc”)
I replaced the above code snippet with

  // This appears to work, but seems like overkill...
  TF1 *f = fGraph->GetFunction("calibFunc");
  TList *l = fGraph->GetListOfFunctions();
  l->Remove(f);
  delete f;
  f = new TF1("calibFunc"...)
  f->SetParameters(...)
  l->Add(f);

My problem is either fixed, or has become so intermittent that I cannot detect it.

Ed

Hi Ed,
compilation of programes with ROOT requires
setting /GR option for compiler.
This option is not default in VisualStudio7

You can set it in VisualStudio7 by

Properties-> C/C++ -> Language -> Enable Run-Time info

It could be a reason of yours crash.

Regards. Valeriy

Hi Valeriy,
I don’t use VisualStudio7 - still on 6. The /GR option is set in my projects.

Any comments on the code snippets above? Is the first one incorrect? If its not, I’ve definately got another latent defect in my code…

Thanks…

Ed

Hi Ed,

A priori, both code snippets should be doing the exact same thing.
In the first on you should be able to do:

// This appears to be wrong, but I don't know why... TF1 *f = fGraph->GetFunction("calibFunc"); delete f; Assert( fGraph->GetFunction("calibFunc") == 0);

Cheers,
Philippe.