|
Boost : |
From: John Maddock (john_at_[hidden])
Date: 2004-01-25 11:33:23
> > 2) An explicit constructor can catch sloppy code:
>
> > std::string trim(const std::string & s)
> > {
> > return regex_replace(s, "\\A\\s+|\\s+\\z", ""); // inefficient use of
> > non-explicit constructor
> > }
>
> > In this case the code can be much more effieciently expressed as:
>
> > std::string trim(const std::string & s)
> > {
> > static const boost::regex e("\\A\\s+|\\s+\\z");
> > return regex_replace(s, e, "");
> > }
>
> Is the behaviour of this in a multiple-threaded environment correct?
I was hoping no one would ask that!
The answer is : it depends upon the compiler, but currently most do *not*
initialise static data in a thread safe manner, I believe that Comeau may be
an exception to that rule, but I'm not certain about that.
Provided you don't want to call the procedure during program startup, you
can just make the data a global variable:
static const boost::regex e("\\A\\s+|\\s+\\z");
std::string trim(const std::string & s)
{
return regex_replace(s, e, "");
}
and then that is thread safe, albeit less elegant.
Otherwise you need to add a mutex that can be statically initialised:
std::string trim(const std::string & s)
{
static mutex_type m = STATIC_MUTEX_INITIALISER;
mutex_type::scoped_lock l(m);
static const boost::regex e("\\A\\s+|\\s+\\z");
return regex_replace(s, e, "");
}
However this uses "too much" locking since we need only lock during object
construction, there may be better versions available, but they generally
rely on OS specific features like test and set on a pointer (that's why it
would be far better for the compiler too handle this).
Such a mutex type does not yet exist in boost, but pthread.h supplies one if
you're using POSIX threads, and I have a portable (ish) version that I'm
using for a future regex release, and which may also get submitted to Boost
at some point.
John.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk