 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Joerg Richter Guest
|
Posted: Thu Oct 30, 2003 10:34 am Post subject: Singleton pattern unsafe? (single threaded) |
|
|
Hi group,
I often use this code to create singletons:
-----
Instance* instance = 0;
Instance* getInstance()
{
if( !instance )
instance = new Instance;
return instance;
}
-----
Now I observe in one of our programs that the new is called more than
once. Note that we don't use threads!
I see from the callstack that the >new< calls some static constructors
which in turn call this getInstance function. But the instance
variable is not yet set, so another new will be made. This second new
calls other constructors. But this isn't relevant now.
I can't find anything in the standard that prohibits this behavior. So
I suppose the compiler (GCC 3.2.1) is right.
I only see the following implementation as an alternative:
-----
Instance* getInstance()
{
static Instance instance;
return &instance;
}
-----
| Quote: | From what I know this should always work (with one thread), opposite
to the first implementation. |
I hope you can confirm both facts.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Andrea Griffini Guest
|
Posted: Fri Oct 31, 2003 1:41 am Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
On 30 Oct 2003 05:34:15 -0500, [email]j_richter (AT) gmx (DOT) de[/email] (Joerg Richter) wrote:
| Quote: | Now I observe in one of our programs that the new is called more than
once. Note that we don't use threads!
|
I do not think your implementation is using multiple threads
to initialize the static instances; multithreading is not
even considered in the C++ standard (where the model is of
a sequential machine) so any observable effect would make
such a compiler blatantly non-conformant.
May be the constructor indirectly calls code that calls the function
to get the singleton ? If this is the case then IMO you have a logic
problem; your code in other words says that to create an instance
of that class you need an already created instance of that class...
and this is a clear nonsense.
Another possibilit is that the constructor you need to call
functions that must rely on the yet-to-be-constructed object
(not sure to do what: the constructor didn't complete... is
the object usable anyway ?) then something you can do is
setting the pointer to the instance using "this" from the
first instruction in the constructor. IMO this is still
questionable from a logical point of view (an object is not
really itself until the constructor completes) but may work.
| Quote: | I only see the following implementation as an alternative:
-----
Instance* getInstance()
{
static Instance instance;
return &instance;
}
|
I don't think this is going to help if the constructor
of Instance directly or indirectly calls getInstance.
Sure the address is going to be ok... but who relies
on the result from getInstance in that phase will use
a potentially non-yet-completely-functional object.
The resulting code is IMO a typical case in which seemingly
innocent changes can (and so will) disrupt the lucky
combination that got it somewhat apparently working.
More generally in my experience using lazy construction
with that kind of singleton pattern seems paying off at
first, but gets ugly as the complexity increases (and
horribly ugly if you add the multithreading issue).
In the years I changed opinion about this point, so
now initialization and shutdown is normally explicitly
handled and *planned*.
Andrea
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Balog Pal Guest
|
Posted: Fri Oct 31, 2003 2:59 am Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
"Joerg Richter" <j_richter (AT) gmx (DOT) de> wrote
| Quote: | Instance* instance = 0;
Instance* getInstance()
{
if( !instance )
instance = new Instance;
return instance;
}
-----
Now I observe in one of our programs that the new is called more than
once. Note that we don't use threads!
|
Then the only problematic calls possible are recursive. IOW happen between
if and =.
And if that happens you sure have a problem.
| Quote: | I see from the callstack that the >new< calls some static constructors
which in turn call this getInstance function.
|
Bingo. They better shouldn't. I wonder how you get out of an infinite
recursion loop.
OTOH, if you get out f that loop, and those statics are function-local
statics, it's a sign that the compiler flags their creation before
construction happens, so the next recursing call will not call into the
ctor, but present that object to the caller -- but that object is not yet
fully constructed! And the caller use that half-baked object.
| Quote: | But the instance
variable is not yet set, so another new will be made. This second new
calls other constructors. But this isn't relevant now.
|
Sure it is. You must break the circular dependency some way, or it it's a
half--circle, you shall force creation of the object at the start of the
chain.
| Quote: | I can't find anything in the standard that prohibits this behavior. So
I suppose the compiler (GCC 3.2.1) is right.
I only see the following implementation as an alternative:
-----
Instance* getInstance()
{
static Instance instance;
return &instance;
}
|
That's much more straightforward than your version, but it must have a
similar problem in your case.
| Quote: | From what I know this should always work (with one thread), opposite
to the first implementation.
|
It is basically the same as yours. With maybe a slight modification:
char instance_holder[sizeof(instance)];
bool constructed = false;
Instance* getInstance()
{
if( !constructed)
{
constructed = true;
instance = new (instance_holder) Instance; // equivalent to call
Instance::Instance()
}
return instance;
}
if that ctor somehow invokes getInstance(), you're hosed again.
If, however the allocation part of new is that calls to getInstance(), the
function-local thing really solves the problem. [but global op new shall not
do that, and having class-specific op new is unlikely for a singleton IMHO.]
Paul
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Severin Ecker Guest
|
Posted: Fri Oct 31, 2003 3:01 am Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
hi!
| Quote: | Instance* instance = 0;
Instance* getInstance()
the pointer to instance and the getinstance have to be static (make copy and |
default contstructor private)
class Instance {
static Instance *instance;
Instance() {};
Instance(const Instance &);
Instance &operator=(const Instance &);
public
static Instance *getInstange();
};
....
i use the same scheme to create singletons, but it just works fine. (hmm,
well actually i'm using the vc6 compiler, so i don't know if something's
screwed up there)
but as far as i know, the above example is a completly legal singleton.
regards,
sev
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Steve Guest
|
Posted: Fri Oct 31, 2003 3:01 am Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
Joerg Richter wrote:
| Quote: | Hi group,
snip
I only see the following implementation as an alternative:
-----
Instance* getInstance()
{
static Instance instance;
return &instance;
}
-----
Hi Joerg, |
This is partly correct, if it is not static you can end up creating
multiple instances, but in this sample you didn't create the initial
instance! However there is another problem you have not mentioned. You
must hide the constructor to make sure that getInstance is the only way
to get an instance. There is a bit more to singletons than you think.
I suggest you look up Singleton in [GoF], they will explain it far
better than I can. There is almost certainly a good explanation online
too (have you searched Google groups?).
Steve
[Gof] "Design patterns : elements of reusable object-oriented software"
by Erich Gamma, Richard Helm, Ralph Johnson, John Vissides
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maciej Sobczak Guest
|
Posted: Fri Oct 31, 2003 3:03 am Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
Hi,
Joerg Richter wrote:
| Quote: | I often use this code to create singletons:
-----
Instance* instance = 0;
Instance* getInstance()
{
if( !instance )
instance = new Instance;
return instance;
}
-----
|
Well, the singleton object will not be released (and its destructor will
not be called), unless you do something special about it and release the
object by hand (for example in the atexit() function).
Another variant of your code (assuming you do not want everybody to have
access to the global pointer) would be;
Instance * getInstance()
{
static Instance *instance = new Instance;
return instance;
}
Which is quite similar to your second example.
But let's continue.
| Quote: | Now I observe in one of our programs that the new is called more than
once. Note that we don't use threads!
I see from the callstack that the >new< calls some static constructors
which in turn call this getInstance function.
|
There is no such a thing like "static constructor", I understand that
you mean "constructor of static object".
It is possible to have the Instance created many times, but this points
to the serious flaw in your program. If the Instance constructor
accesses some functions that in turn (indirectly via constructors of
their local, static objects) try to access the singleton object again,
you clearly have some cyclic dependencies between the objects - here
they are very dangerous. Try to break it up so that the singletons are
leafs (they do not create other objects) or at least that you do not
have cycles.
| Quote: | I can't find anything in the standard that prohibits this behavior.
|
Right.
| Quote: | I only see the following implementation as an alternative:
-----
Instance* getInstance()
{
static Instance instance;
return &instance;
}
-----
|
It is not any alternative if you do not break the cycles.
Moreover, now it is worse than before. 6.7/4 says that local static
objects are considered to be initialized "upon the completion of their
initialization". This means that if the constructor of your static
object (instance) calls some functions that in turn call getInstance()
again, then the control will reach the static object recursively, still
in the not-yet-initialized-state, which triggers undefined behavior (the
same paragraph).
When you put some output statement in the Instance constructor, you will
likely see the output appearing repeatedly on the screen (this is what I
can see with gcc 3.3.1, when the Instance constructor calls some
function which in turn calls getInstance()).
| Quote: | From what I know this should always work (with one thread), opposite
to the first implementation.
|
No, it is the other way round.
If you have cycles, then the first implementation will create the
"singleton" object twice (or many times, depending on how the other
functions look like), leaking resources, but at least it is quite easy
to predict the results. It is broken in the design, but predictable.
When cycles are involved, the second implementation is *always*
undefined behavior.
Note that threads are not important here.
When threads are involved, nothing sure can be said keeping the standard
in hand, but we can make some safe bets about popular platforms.
The following function (I use reference instead of pointer as a return
value here):
Instance & getInstance()
{
static Instance i;
return i;
}
will safely create the singleton object IF you ensure that the first
calling thread will completely initialize the object before other
threads come. Later, it should be OK for many threads to call
getInstance(). Well, at least, popular compilers generate code that is
safe with multiple threads, but this premise is safe *after* the
singleton object is initialized. This can be easily ensured by having
the main thread calling all the getInstance()-like functions before
other threads are started. Most of the time it can be done this way,
because usually one thread in the application is special (it exists as
the first thread) and can be used for such initialization. In the rare
cases where it cannot (when there are many threads that are "first", for
example when you want to lazy-initialize singletons), you have to use
some more complicated solutions, which are so convoluted that even
experts happen to slip on it.
| Quote: | I hope you can confirm both facts.
|
Try to break the cycles. Write your code so that the singleton object
can be constructed without invoking the getInstance() function again.
Then - both versions will be safe, with preference (no use of raw
pointers) on the second implementation.
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Matt Seitz Guest
|
Posted: Fri Oct 31, 2003 10:05 am Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
Joerg Richter wrote:
| Quote: | I hope you can confirm both facts.
|
Yes, your analysis of the problem and solution are correct. See "Initialization
of Nonlocal Variables" (section 9.4.1) in THE C++ PROGRAMMING LANGUAGUE (3rd
Edition).
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ralf Guest
|
Posted: Fri Oct 31, 2003 10:06 am Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
Hi,
the singleton Pattern has some havy consequences. You need to have a good
concept of using it. To implement it with a static instance is only one
little step. A good book describing how to apply singletons is "Modern C++
Design" from Andrei Alexandrescu.
Some basic ideas you get from the article:
http://www.oop-trainer.de/Themen/Singleton.html
The article is German. Looking to your name I think it will be no problem
for you. ;-)
Ralf
www.oop-trainer.de
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
JarlOstensen Guest
|
Posted: Fri Oct 31, 2003 10:23 am Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
[email]j_richter (AT) gmx (DOT) de[/email] (Joerg Richter) wrote in message news:<59aed.0310290151.6187af22 (AT) posting (DOT) google.com>...
| Quote: | Hi group,
I often use this code to create singletons:
-----
Instance* instance = 0;
Instance* getInstance()
{
if( !instance )
instance = new Instance;
return instance;
}
-----
Now I observe in one of our programs that the new is called more than
once. Note that we don't use threads!
I see from the callstack that the >new< calls some static constructors
which in turn call this getInstance function. But the instance
variable is not yet set, so another new will be made. This second new
calls other constructors. But this isn't relevant now.
|
This is exactly the risk with the singleton pattern, and one of the
most common problems with its use: The singleton pattern is used to
ensure that only one instance of a particular class exists, _not_ to
ensure correct initialisation order!
What you should do is to use a common initialisation point for all
singletons in your application. I.e, you have a point somewhere in
your "main" which creates the singletons in the correct order. The
singleton constructors should _not_ rely on other singletons, but an
initialisation (or "post-create" method), can.
I.e.
Singleton
ctor - Only initialises local state
"Init function" - Initialises state that might have external
dependencies.
So, don't confuse singletons with "create-order-independent"!!
Don't feel bad about it though...we've all been there... :)
| Quote: |
I can't find anything in the standard that prohibits this behavior. So
I suppose the compiler (GCC 3.2.1) is right.
I only see the following implementation as an alternative:
-----
Instance* getInstance()
{
static Instance instance;
return &instance;
}
-----
From what I know this should always work (with one thread), opposite
to the first implementation.
|
....but again it doesn't really solve your problem, it just softens the
blow.
Regards
-=jarl
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Lally Singh Guest
|
Posted: Fri Oct 31, 2003 12:15 pm Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
[email]j_richter (AT) gmx (DOT) de[/email] (Joerg Richter) wrote in message news:<59aed.0310290151.6187af22 (AT) posting (DOT) google.com>...
| Quote: | Hi group,
I often use this code to create singletons:
-----
Instance* instance = 0;
Instance* getInstance()
{
if( !instance )
instance = new Instance;
return instance;
}
-----
Now I observe in one of our programs that the new is called more than
once. Note that we don't use threads!
I see from the callstack that the >new< calls some static constructors
which in turn call this getInstance function. But the instance
variable is not yet set, so another new will be made. This second new
calls other constructors. But this isn't relevant now.
|
Unless I'm reading you wrong, you're saying that the constructor (or
some code it calls) has a circular dependency? if getInstance() ends
up calling itself, you've got problems. One way to fix is with
another 'in-progress' flag:
static bool in_progress;
if (!instance && !in_progress ) {
in_progress = true;
instance = new Instance;
in_progress = false;
}
But, IMHO, I use the other method. OTOH, that requires static
allocation.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Torjo Guest
|
Posted: Fri Oct 31, 2003 2:50 pm Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
[email]j_richter (AT) gmx (DOT) de[/email] (Joerg Richter) wrote in message news:<59aed.0310290151.6187af22 (AT) posting (DOT) google.com>...
| Quote: | Hi group,
I often use this code to create singletons:
-----
Instance* instance = 0;
Instance* getInstance()
{
if( !instance )
instance = new Instance;
return instance;
}
-----
Now I observe in one of our programs that the new is called more than
once. Note that we don't use threads!
I see from the callstack that the >new< calls some static constructors
which in turn call this getInstance function. But the instance
variable is not yet set, so another new will be made. This second new
calls other constructors. But this isn't relevant now.
I can't find anything in the standard that prohibits this behavior. So
I suppose the compiler (GCC 3.2.1) is right.
I only see the following implementation as an alternative:
-----
Instance* getInstance()
{
static Instance instance;
return &instance;
}
-----
From what I know this should always work (with one thread), opposite
to the first implementation.
I hope you can confirm both facts.
|
Not quite :(
(see standard 6.7/4)
It's implementation-defined when an static object is marked as
fully-constructed.
In other words, an implementation might - behind the scenes - do
something like this:
static bool initialized = false;
if ( !initialized) {
instance = new Instance;
initialized = true;
}
So, in your case, you would have an infinite loop.
What you can do is the following (which will work single-threaded, but
still might cause undefined behaviour):
Instance* getInstance()
{
static bool initialized = false;
static Instance* instance = 0;
if( !initialized ) {
initialized = true;
instance = new Instance;
}
return instance;
}
This will return NULL while the object is ***initializing***.
Best,
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Joerg Richter Guest
|
Posted: Fri Oct 31, 2003 5:23 pm Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
Andrea Griffini <agriff (AT) tin (DOT) it> wrote
| Quote: | May be the constructor indirectly calls code that calls the function
to get the singleton ?
|
I am aware of this problem. Acually Instance is a typedef to
std::map<...>. So no code of mine should be executed when the
constructor runs.
| Quote: | Another possibilit is that the constructor you need to call
functions that must rely on the yet-to-be-constructed object
(not sure to do what: the constructor didn't complete... is
the object usable anyway ?) then something you can do is
setting the pointer to the instance using "this" from the
first instruction in the constructor. IMO this is still
questionable from a logical point of view (an object is not
really itself until the constructor completes) but may work.
I only see the following implementation as an alternative:
-----
Instance* getInstance()
{
static Instance instance;
return &instance;
}
I don't think this is going to help if the constructor
of Instance directly or indirectly calls getInstance.
|
This isn't the case. To me it seems the compiler decided to initialize
other translation units during the call to new and as a consequence
getInstance is called again.
Is there any word in the standard that says that all dynamic
initialization must be executed one after another? I mean is the
compiler allowed to interrupt the dynamic initialization of an object
somewhere to initialize an other object? I think so. I.e. wenn you
call in your dynamic initialization one function from another
translation unit then all static objects from the other translation
unit must be initialized before the function call occures. And this
other initialization can call back to your first translation unit and
you have a similar problem I have. I know, then you have a cyclic
dependency between translation units (not functions!) an the design is
flawed, but the program should still work in this case.
So I think getInstance and dynamic initialization of static objects
can't work together.
| Quote: | In the years I changed opinion about this point, so
now initialization and shutdown is normally explicitly
handled and *planned*.
|
We are planning to replace all dynamic initialization with a framework
that handles all initialization and finalization in a well defined
order. So the above problem will not exist anymore (for us).
Joerg
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Joerg Richter Guest
|
Posted: Fri Oct 31, 2003 11:31 pm Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
"Balog Pal" <pasa (AT) lib (DOT) hu> wrote
| Quote: | Now I observe in one of our programs that the new is called more than
once. Note that we don't use threads!
Then the only problematic calls possible are recursive. IOW happen between
if and =.
And if that happens you sure have a problem.
|
No there are no cyclic dependecies between functions involved. At most
between translation units. See my answer to Andrea.
| Quote: | I see from the callstack that the >new< calls some static constructors
which in turn call this getInstance function.
Bingo. They better shouldn't. I wonder how you get out of an infinite
recursion loop.
|
The program runs fine. No infinite loop here. I saw at most three
getInstance calls on the stack. The problem in my case is that the
registry (instance) is constructed more than once and you don't see
the elements that were inserted before the last construction. In my
case we noticed it during runtime that the registry contains to few
elements.
| Quote: | But the instance
variable is not yet set, so another new will be made. This second new
calls other constructors. But this isn't relevant now.
Sure it is. You must break the circular dependency some way, or it it's a
half--circle, you shall force creation of the object at the start of the
chain.
|
Sorry too easy. There are no cyclic function calls involved.
| Quote: | I only see the following implementation as an alternative:
-----
Instance* getInstance()
{
static Instance instance;
return &instance;
}
That's much more straightforward than your version, but it must have a
similar problem in your case.
|
It has, but this version cores at initialization time oposed to the
runtime problems with the other code fragment.
| Quote: | From what I know this should always work (with one thread), opposite
to the first implementation.
It is basically the same as yours. With maybe a slight modification:
char instance_holder[sizeof(instance)];
bool constructed = false;
Instance* getInstance()
{
if( !constructed)
{
constructed = true;
instance = new (instance_holder) Instance; // equivalent to call
Instance::Instance()
}
return instance;
}
if that ctor somehow invokes getInstance(), you're hosed again.
|
IMHO that can be the case even if you don't have cyclic function
calls. All version work correct when no dynamic initialization is
involved (and no recursive calls), but when dynamic initialization
comes into play then IMHO there is no way to make it work in all
cases.
| Quote: | If, however the allocation part of new is that calls to getInstance(), the
function-local thing really solves the problem. [but global op new shall not
do that, and having class-specific op new is unlikely for a singleton IMHO.]
|
Function-local didn't solved it cause there can be indirect calls to
new anyway.
btw. I would also say that global new shall not call other dynamic
initialization. But this seems the case here.
Joerg
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Joerg Richter Guest
|
Posted: Fri Oct 31, 2003 11:32 pm Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
Hi,
| Quote: | I see from the callstack that the >new< calls some static constructors
which in turn call this getInstance function.
There is no such a thing like "static constructor", I understand that
you mean "constructor of static object".
It is possible to have the Instance created many times, but this points
to the serious flaw in your program. If the Instance constructor
accesses some functions that in turn (indirectly via constructors of
their local, static objects) try to access the singleton object again,
you clearly have some cyclic dependencies between the objects - here
they are very dangerous. Try to break it up so that the singletons are
leafs (they do not create other objects) or at least that you do not
have cycles.
|
Everything would be easy if there were recursive function calls. But
there are no cycles.
| Quote: | From what I know this should always work (with one thread), opposite
to the first implementation.
No, it is the other way round.
If you have cycles, then the first implementation will create the
"singleton" object twice (or many times, depending on how the other
functions look like), leaking resources, but at least it is quite easy
to predict the results. It is broken in the design, but predictable.
When cycles are involved, the second implementation is *always*
undefined behavior.
|
But only in the case of cycles. I only have the problem when dynamic
initialization in involved. Everything works fine when I use this
pattern without dynamic initialization.
Please see my answers to the other posters too.
Joerg
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Balog Pal Guest
|
Posted: Sat Nov 01, 2003 9:58 am Post subject: Re: Singleton pattern unsafe? (single threaded) |
|
|
"Lally Singh" <lallysingh (AT) mac (DOT) com> wrote
| Quote: | Unless I'm reading you wrong, you're saying that the constructor (or
some code it calls) has a circular dependency? if getInstance() ends
up calling itself, you've got problems. One way to fix is with
another 'in-progress' flag:
static bool in_progress;
if (!instance && !in_progress ) {
in_progress = true;
instance = new Instance;
in_progress = false;
}
|
Cool. But Do you remember it's inside the GetInstance() function that must
return a fully constructed instance? What you return if you detected that
in_progress? ;-)
Paul
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|