[Insight-developers] itk::LightObject non-threaded

Ken Martin ken.martin@kitware.com
Fri, 5 Apr 2002 09:39:28 -0500


If you do not already have a convention for multithreading in ITK,
then you must first determine your convention before anything else.
There are a couple options I know about and they have serious
consequences. I've only worked a little with this so others may have
better information. I'm sure there is some formal terminology as well.

1) No thread safety - clearly this is easy to implement but prevents
anyone from using the advantages of multithreaded programming.

2 A) What I call instance level thread safety. This is what VTK tries
to do although it is not done that well. In this multiple threads can
be used but a single instance can only be safely accessed from a
single thread. This means that your code must protect all static data
with critical sections. If the static data is accessed in inner loops
this will cause a noticeable hit in performance. B) If an instance
wants to use multithreading within a method then it must be careful
not to write to any storage location that another thread could read
from or write to. This takes some extra effort on the part of the
developer.

3) Full multithread safety. In this case an instance may be accessed
by multiple threads at the same time. This is the easiest to work with
for an application developer. The toolkit development isn't that bad
either because almost everything will have the same thread based mutex
protection in it. (static methods being one exception) Specifically,
every method in the toolkit that reads from an ivar or writes to an
ivar must be put into a thread based critical section. For a toolkit
like ITK that means pretty much every method will have to check a
critical section.  This includes methods such as operator[] (it does a
read) etc. I mention thread based critical sections because many
methods do something like...

void foo::bar()
{
  this->GetCriticalSectionForThread();
  for (i = 0; i < this->NumberOfWidgets; ++i)
    {
    ...
    this->RealizeWidget(this->Widgets[i]);
    }
  this->ReleaseCriticalSectionForThread();
}

void foo::RealizeWidget(widgets *w)
{
  this->GetCriticalSectionForThread();
  // do something
  this->ReleaseCriticalSectionForThread();
}


The GetCriticalSectionForThread in RealizeWidget, when called from
bar(), will determine that the current thread already owns the
critical section for this instance so it will not block, but instead
increment that instance's CriticalSection count for that thread. The
Release does the opposite. The other approach is to require that all
ivar accesses (even within methods of the class) go through Set/Get
methods that have the critical sections in them and they return all
native data types by reference. (no float *GetPosition() code unless
the float * returned is a copy of the instance's ivar that was
allocated on the heap and will be freed by the caller of
GetPosition())

If you decide to go with a full multithread safe toolkit you will have
to make it a compile time option because the performance penalty will
be enormous. Even multithreaded languages like Java require special
keywords for methods that need to be multithread safe.

The key is to come up with a formal statement on how ITK will support
multithreading. Once that has been decided the implementation details
will easily follow.

Thanks
Ken

> -----Original Message-----
> From: insight-developers-admin@public.kitware.com
> [mailto:insight-developers-admin@public.kitware.com]On
> Behalf Of Luis
> Ibanez
> Sent: Thursday, April 04, 2002 8:28 PM
> To: Miller, James V (CRD); Insight Developers
> Subject: [Insight-developers] itk::LightObject non-threaded
>
>
>
> Jim,
>
> Following up on your clarification of the itkLightObject
> SmartPointer and their relation with the Mutex....
>
> How about adding a class "itkLightObjectNonThreaded" ?
>
> It will basically be the itkLightObject without the Mutex
> in the Register/Unregister methods (and without the
> mutex lock ivar itself), only the reference counter.
>
> Objects deriving from this new class will still be able to
> use smart pointers and enjoy of the convenience of
> automatic memory collection while still being fast in
> pointer copying.
>
> BTW it is worth to clarify that the access itself is *not*
> penalized by the mutexlock, only the copy of the SmartPointer
> into another SmartPointer is.  Dereferencing the object doesn't
> require to modify the reference counting and it is done by an
> inlined method in the SmartPointer.  Any access of type:
>
>             smartPointer->      or       *smartPointer
>
> should be as direct as using the normal pointer.
> (except when compiling with debugging, which will prevent
> this functions from being inlined...)
>
>
> In order to avoid code duplication with this new
> itk::LightObjectNonThreaded  class we can make:
>
>      itk::LightObject
>
>           derive from
>
>    itk::LightObjectNonThreaded
>
> that will leave itk::LightObject with only the additional
> code required for the Mutexlock: namely the mutexlock
> ivar and the overload for the virtual methods:
>
>         Register() / UnRegister() / SetReferenceCount()
>
>
> With this combination, classes that are expected to be shared
> from diferent threads should derive from itk::LightObject (or
> itk::Object)  while classes that are limited to be used from inside
> a single thread will derive from itk::LightObjectNonThreaded
> and still be able to use SmartPointers as strategy for memory
> collection.  Current SmartPointers could be used without change.
>
>
> How do you find this option ?
>
>
> Luis
>
>
>
>
>
>
> _______________________________________________
> Insight-developers mailing list
> Insight-developers@public.kitware.com
> http://public.kitware.com/mailman/listinfo/insight-developers