|
Boost : |
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2007-04-20 22:48:48
So if I understand this correctly, you basically have something
similar to this (but using template magic):
static boost::function<void ()> b_void_func;
static boost::function<void (int)> b_void_func_int;
static boost::function<void (int,int)> b_void_func_int_int;
// etc for different return types and param types,
// magically generated as needed by the compiler
and you also have (and also magically generated):
static void c_func()
{
return b_func();
}
static void c_func_int(int i)
{
return b_func_int(i);
}
// etc for all necessary combinations
(And you also have statics for each tag:
static boost::function<void()> b_func_magictag;
but we can leave that aside for now)
The important part is that each function pointer is *static*.
So make_c_function() in effect 'finds' the right c_func and returns it:
SomeFunctionType make_c_function(boost::function f)
{
// using template magic set the correct ***static*** boost function:
// let's pretent it is b_func
b_func = f;
// and magically return the right c_function, let's say c_func:
return c_func;
}
now imagine 2 threads
// thread 1
cf1 = make_c_func(mybind1)
cf1(); // call cf1 - it calls mybind1
// thread 2
cf2 = make_c_function(mybind2)
cf2(); // calls cf2 - ie mybind2, right???
but if the threads happen to be running at the same time:
// thread1 gets a timeslice:
cf1 = make_c_function(mybind1); // internally sets *global* b_func = mybind1
// say thread2 gets a timeslice now:
cf2 = make_c_function(mybind2); //sets *global* b_func = mybind2
cf1(); // calls c_func, which cals mybind1? NO it calls mybind2.
That's the threadsafety problem.
So, it's OK for some uses, and maybe using tags you could keep track
of your uses better (ie this thread always uses this tag, etc), but if
you are dynamically creating threads (ie 1 per server request, etc),
then this can't easily be used.
Tony
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk