Hi Benjamin,
On 2011-08-11 you wrote:
>
> What I would try to avoid at all cost is non-trivial initialization in a
> *constructor* for a static object. I listed lazy initialization as one
> alternative possibility. Just to make sure we re talking about the same
> concept, what I mean is to add some code like
>
> if (!this->initialized) this->initialize();
>
> at the start of each method. I may be wrong but I can't think of any
> subsystem where this approach cannot be used instead of calling
> initialize() from a constructor.
We're not really talking about constructing complicated objects, more the
ability to run code at initialization time. Take this example from libCom:
static int done = timeRegister();
I don't care about the value of done, I just need to run the timeRegister()
routine to register my time-proviers before anyone tries to ask for the
current time.
Your code above is not SMP-safe, and actually it's not even safe on a UP
system in some circumstances. If there are at least two threads running then
they can both execute the initialize() method simultaneously (before the other
thread sets the initialized member), which is obviously a Bad Thing™. You
can't even protect the initialize() routine with its own mutex because someone
has to create the mutex for the routine to lock. The epicsThreadOnce()
routine was designed to solve exactly this problem, and I believe we have
already converted all the code in Base to use it. The result looks like this:
static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
static void once(void *junk)
{ ... }
FILE * epicsShareAPI doSomething(...)
{
epicsThreadOnce(&onceId, once, 0);
...
}
If two threads on different CPUs call doSomething() simultaneously, one of
them will execute the once() routine and the other one will be blocked until
once() has returned.
Unfortunately with the existing implementation of epicsThreadOnce() every call
to doSomething() results in a mutex lock and unlock of a single global mutex,
which is obviously not good for parallelism and performance. We don't want to
incur that cost for some APIs that are used frequently, so lazy initialization
isn't always a good idea.
> > On vxWorks and some RTEMS systems the NTPTimeSync and ClockTimeSync
> > threads are started from a static initializer, and they also get
> > registered with the taskwd subsystem which lazily starts its own thread
> > as a result:
>
> As I said, starting threads lazily is not as evil as doing it directly from
> a constructor for a static object, i.e. before main() starts.
SMP-safe lazy init requires making a call to epicsThreadOnce() every time you
use that subsystem. Hopefully we can remove the need to take a mutex every
time by switching to atomic operations in 3.15, but we'll try to hide that
from users and still make epicsThreadOnce() the API you use.
> I recognize that logging is one of the exceptions to my rule (1) but
> (again) we can use lazy initialization here.
We already do.
> > > (5) epicsThreadOnce should also be avoided wherever possible. Using it
> > >
> > > means objects cannot be freely passed between threads which is
> > > detriment to composability.
> >
> > But as Jeff implied, epicsThreadOnce() is essential to coding lazy
> > initialization correctly on an SMP system.
>
> I would like to see the argument that leads to such a conclusion.
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
- Andrew
--
Optimization is the process of taking something that works and
replacing it with something that almost works, but costs less.
-- Roger Needham
- Replies:
- Re: c++ static initialization Benjamin Franksen
- References:
- c++ static initialization Jeff Hill
- Re: c++ static initialization Andrew Johnson
- Re: c++ static initialization Benjamin Franksen
- Navigate by Date:
- Prev:
Re: c++ static initialization Eric Norum
- Next:
RE: c++ static initialization Jeff Hill
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
<2011>
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: c++ static initialization Eric Norum
- Next:
Re: c++ static initialization Benjamin Franksen
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
<2011>
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|