Perhaps I missed something, but have you looked at the call stack of the
"extra" threads in the debugger? IIRC, if you link to the multithreaded
Windows runtime, you will get background threads as a matter of course.
You should be able to look at the call stack of each thread, and
determine whether or not it is one created in your 1...N loop. You
might try setting N to 2 before you do that. Does the number of "extra"
threads stay constant if you vary N?
John
________________________________
From: boost-users-bounces@lists.boost.org
[mailto:boost-users-bounces@lists.boost.org] On Behalf Of Terrimane
Pritchett
Sent: Monday, April 27, 2009 1:00 PM
To: boost-users@lists.boost.org
Subject: Re: [Boost-users] [BOOST THREAD] Threads Spawning Unexpectedly
I suspect my problem continued problem lies with boost::tokenizer...for
more on that skip to the bottom of this post.
First I want to respond to some of the valid concerns presented to me.
The input data *shouldn't* be shared. It shouldn't be but as there is
something wrong here I must validate all assumptions.
I am essentially using a boost::thread to process a file for 1 to N
files. After I get it working I'll control how many files are processed
at once etc. What is relevant here is that each file is processed is a
separate thread and there is no communication or sharing of data between
threads.
(don't misinterpret this as criticism...I LOVE all things boost believe
me!)
If boost::lexical_cast were 100% thread safe I would have no need for
guarding access to calling it. Igor R mentioned boost::lexical_cast is
thread safe because the function has it own local streambuf instance. I
need to do more research but my understanding is that this isn't the
case. I was led to believe boost::lexical_cast was not thread safe
mostly by reading this discussion:
http://lists.boost.org/Archives/boost/2006/09/109907.php
Basically, if locale,stringstream etc can access global data (which they
may) and boost::lexical_cast is built on top of them without protections
in place to guarantee thread safety (which I cannot readily see in the
documentation or code) then boost::lexical_cast is not thread safe.
Before I'm taken out back and beaten I admit I haven't spent much time
exploring how boost::lexical_cast is implemented. I try to stay away
from implementation details when implementations may change and I may be
tempted to leverage something I shouldn't. I am open to knowledge so by
all means impart some upon me if have some to offer.
Back to my problem. Its been suggested that some other library is
spawning threads behind my back. I can report that is not the case. I
have moved back to the single-threaded implementation and *ONLY* my main
thread is a part of my application's process. When I move to the
multi-threaded implementation that leverages boost::thread I now have
new threads appearing...some I spawned...others I did not. The only
difference between both implementations is the inclusion of Boost
Threads to the project. If some library were spawning threads behind my
back I would see them in the single threaded application at some point
and also be able to decipher what kind of threads they were. Neither
MSVC or the OS detects anything other than my Main thread running in my
single threaded implementation.
Something must explain where the extra threads are coming from.
I have full confidence that boost::lexcial_cast is getting bad data.
The question for me is how is that possible? Data *shouldn't* be
shared. I *shouldn't* be seeing more threads than I explicitly create.
I may be able to answer how boost::lexical_cast is getting bad
data...but I don't have any clues as to where my extra threads are
coming from.
My suspicion in that boost::tokenizer is supplying my calls to
boost::lexical_cast with bad data. I looked at the documentation for
boost::tokenizer and saw no mention of thread safety anywhere. I then
took a look at the source of the boost token_iterator class since it is
really what does the heavy lifting in tokenizing strings. Specifically
I had a look at token_functions.hpp. Here it can be seen that the
standard cctype library is leveraged. This library may not be thread
safe because implementors are allowed to leverage global/static data
(particularly locales if memory serves) without regard for shared access
by multiple threads.
While I have guarded boost::lexical_cast I have not guarded access to
boost::tokenizer or its iterator. I will attempt to add proper
protections while I await any incoming thoughts and input on the matter.
Shon
P.S. I did catch boost::bad_lexical cast...it never suspected the cast
was getting bad data. I wanted to know why. Still, if anyone is
interested in what sort of bad data is coming in causing the exception
to be thrown here is a sample.
try
{
std::cout<<"string input:
"<<"<begin>"<