Loki's AssocVector versus std::map in mt

  • Follow


I have been experimenting with Factory in a multi-threading setting
and have run into seg faults from as yet unknown place within factory.
 I have done some testing and found that when Factory uses AssocVector
as its associations, I get seg faults roughly 15% of the time with my
test code.  But if I replace the AssocVector with the std::map, I have
not yet run into any seg faults (after about 200 runs).

I was wondering if anyone had experience these types of problems with
AssocVector before and if anyone had any fixes for them.  If not,
could someone suggest what differences between AssocVector and
std::map (some of which are pointed out in the documentation) which
could point to problems using this in a mt setting.  I have a feeling
that the iterators being invalidated by insert and erase operations
are not very mt-friendly, but am wondering if there are any other
standard guarantees that would inhibit its use in its current form.

I also have another question.  How many test runs of a particular mt
test code would you feel safe that it is working correctly (for a
particular environment/computer/compiler)?  For example, you wanted to
see if double-checked locking gives you problems on your testing
environment.  If it succeeded for N number of times which you specify
(10, 100, 1000, ...), would you feel safe using it?  What would be
your N?

Best regards,
John

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply john 8/13/2003 10:00:31 PM

I've tried to keep the multi-threading content to a pertinent minimum.
John, if you want to discuss any of that further,
comp.programming.threads is the right place.
Ah, I see you've been there ...


john-dill@uiowa.edu (John Dill) wrote in message
news:<302c79f4.0308130659.bd1e703@posting.google.com>...
> I have been experimenting with Factory in a multi-threading setting
> and have run into seg faults from as yet unknown place within factory.
> I have done some testing and found that when Factory uses AssocVector
> as its associations, I get seg faults roughly 15% of the time with my
> test code.  But if I replace the AssocVector with the std::map, I have
> not yet run into any seg faults (after about 200 runs).

I'm not at all convinced by the idea of writing code that "statistically
doesn't segfault too often".

<MT-specific>
Multithreaded code is prone to errors that come and go depending on the
machine you use, how many processors it has, etc.
Unless you want this program to stop working the first time you run it
on a different machine, it sounds like you really need to figure out
what is happening, rather than just hoping the change from AssocVector
to std::map fixed the problem. It might just have changed the
characteristics of a race condition so you don't happen to see it with
your current set-up.
</MT-specific>

More generally (and not limited to multithreading), if a program fails
*unpredictably*, you really need to find out what is happening and why,
and fix the logic. Just reducing the frequency of its unpredictable
crashes doesn't sound much good.

> 
> I was wondering if anyone had experience these types of problems with
> AssocVector before and if anyone had any fixes for them.  If not,
> could someone suggest what differences between AssocVector and
> std::map (some of which are pointed out in the documentation) which
> could point to problems using this in a mt setting.  I have a feeling
> that the iterators being invalidated by insert and erase operations
> are not very mt-friendly, but am wondering if there are any other
> standard guarantees that would inhibit its use in its current form.

Well, do you hold on to any iterators after releasing a lock on the
container? AssocVector will invalidate iterators on insert/erase, and
std::map won't (iirc).
In general,

	Container::iterator i( container.find(something) );

	// other code that might change container via erase/insert.
	// In MT code this could be any section where we don't hold a
	// lock on container.

	i->doIt();

is safe only if Container promises not to invalidate iterators, for at
least the set of mutating operations performed on container between getting and
using the iterator i.


> 
> I also have another question.  How many test runs of a particular mt
> test code would you feel safe that it is working correctly (for a
> particular environment/computer/compiler)?  For example, you wanted to
> see if double-checked locking gives you problems on your testing
> environment.  If it succeeded for N number of times which you specify
> (10, 100, 1000, ...), would you feel safe using it?  What would be
> your N?

I prefer to write it correctly.

Testing is still worthwhile, but since bugs can be hidden/exposed due to
changes in timing or scheduling which are outside your control, the only
reliable test would be to run it on every machine, with every set up, it
will ever be used on.

<MT-specific>
You're better off avoiding race conditions in the first place by careful
static analysis IMHO. Ideally this would involve avoiding double-checked
locking, since it isn't correct irrespective of whether it works for
you. This is another (though less likely) case of building something
into your program which might bite you later.
</MT-specific>

> 
> Best regards, John
> 
>       [ See http://www.gotw.ca/resources/clcm.htm for info about ] [
>       comp.lang.c++.moderated.    First time posters: Do this! ]

HTH,
Simon.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply s_j_turner 8/14/2003 6:40:40 PM


I found my main problem.  It turns out that I was using string
literals as keys used in my factory, and was giving a seg fault
somewhere in its creation or copy functions.  Still not sure why the
"literal" seg faults, but using an integer key demonstrated correct
behavior without segfaults for many test runs.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply john 8/15/2003 1:15:18 AM

In article <302c79f4.0308140544.4ba0d242@posting.google.com>,
John Dill wrote:
> I found my main problem.  It turns out that I was using string
> literals as keys used in my factory, and was giving a seg fault
> somewhere in its creation or copy functions.  Still not sure why the
> "literal" seg faults, but using an integer key demonstrated correct
> behavior without segfaults for many test runs.

"Copy-on-write" string implementations are generally not thread-safe.
If you're using copy-on-write strings, you should consider changing
that.  Otherwise you have to be very careful to ensure that strings
passed between threads do not have shared buffers.  With std::string
you can normally do this by calling begin() on them.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Ben 8/16/2003 3:49:41 PM

3 Replies
532 Views

(page loaded in 0.486 seconds)

Similiar Articles:







7/24/2012 3:17:02 PM


Reply: