EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: memory management
From: Benjamin Franksen <[email protected]>
To: Jeff Hill <[email protected]>
Cc: 'Eric Norum' <[email protected]>, 'Ralph Lange' <[email protected]>, 'Matej Sekoranja' <[email protected]>, 'Marty Kraimer' <[email protected]>, 'Andrew Johnson' <[email protected]>, 'Ken Evans' <[email protected]>, 'Bob Dalesio' <[email protected]>, "'Kasemir, Kay'" <[email protected]>
Date: Wed, 02 Mar 2005 22:14:18 +0100
On Wednesday 02 March 2005 20:30, Jeff Hill wrote:
> > > BTW: Functions like c_str are also a real problem from a
>
> thread
>
> > > safe interface perspective.
> >
> > Why?
>
> Andrew has already given a good answer here.

Yes, I understood the problem after I read Andrew's explanation and his 
citation of the standard. I agree that c_str interface of std::string is 
horrible.

> He has mentioned 
> that
> locking is usually provided at a higher level. I agree, but
> should
> mention that when maintaining large multi-threaded
> programs there are possibilities of failing to remember where in
> the function
> call hierarchy the locking must eventually be implemented.
> Snippets of
> code get reused in many different situations. Entry points might
> be called
> without holding the proper lock. I am recently starting to use
> mutex guard
> classes to enforce the locking requirements of interfaces at
> compile time,
> and this approach requires that the interface of each class be
> perfectly
> clear in terms of thread safety, and enforced based on the mutex
> guard that
> must be passed to member functions.

Completely agreed.

> All of those warnings in the 
> standard
> about not using the ptr returned by c_str after the next call to
> a basic_string member function sound like an invitation for race
> condition nightmares when trying to maintain the locking in a
> large multithreaded code.

Completely agreed.

> > > [...]
> > > Note however that the pure virtual string interface in data
> > > access exists to provide us options. We may use almost any
>
> string
>
> > > implementation we would like. This includes standard library
> > > strings and standard library streams should they be found to
>
> be
>
> > > suitable for a particular application.
> >
> > Of course, the smaller your interface, the larger the set of
>
> possible
>
> > implementations that can be fit unto it. Or so it would seem.
> >
> > Unfortunately, however versatile your string interface may
> > be, it imposes an
> > imperative style on the implementation: it completely
> > precludes functional
> > style (immutable) strings. Such strings are *so* much easier
> > to handle, than
> > the traditional mutable ones. Take concatenation as an
> > example. Functional
> > style:
> >
> > 	res = concat(s1,s2);
> >
> > Imperative style:
> >
> > 	res = new string( s1.length() + s2.length() ); // or
> > was it -1 or +1 ???
> > 	res.copy( s1 );
> > 	res.append( s2 );
>
> Take a 2nd look at the stringSegment interface (see below). It
> does
> not preclude user defined operators for your "imperative
> style", and in fact includes interfaces directly supporting it.

You misunderstood my point. Of course it is possible to define a 
functional-looking interface on top of an imperative one. But the imperative 
(mutating) methods are still available, destroying the possibility to 
garantee certain class invariants.

> For example, the write interface that takes a stringSegment can
> be used to append a stringSegment to a stringSegment.

Yes, of course. But this is not what I was talking about.

> class streamWrite {
> public:
>     virtual streamWriteStatus write (
>         const double &, const propertyCatalog & = voidCatalog ) =
> 0;
>     virtual streamWriteStatus write (
>         const int &, const propertyCatalog & = voidCatalog ) = 0;
>     virtual streamWriteStatus write (
>         const long &, const propertyCatalog & = voidCatalog ) =
> 0;
>     virtual streamWriteStatus write (
>         const unsigned &, const propertyCatalog & = voidCatalog )
> = 0;
>     virtual streamWriteStatus write (
>         const unsigned long &, const propertyCatalog & =
> voidCatalog ) = 0;
>     virtual streamWriteStatus write (
>         const epicsTime &, const propertyCatalog & = voidCatalog
> ) = 0;
>     virtual streamWriteStatus write (
>         const class stringSegment &, const propertyCatalog & =
> voidCatalog ) = 0;
> };

The above methods all change the data content of the object. A functional 
interface has no methods to change an existing object.

Instead, a functional string class will provide a number of constructors 
that /create/ strings from a double, an int, etc. Plus a number of functions 
and methods operating on one or more strings to create new ones (substring, 
concat, split, ...).

> > An implementation based on non-contiguous storage, could take
> > advantage of its
> > storage model, and almost completely avoid copying (at the
> > cost of slightly
> > increasing the overall memory footprint).
> > For instance, functional
> > concatenation can be done in constant time (avoiding all
> > allocation and
> > copying).
> > For instance, functional
> > concatenation can be done in constant time (avoiding all
> > allocation and
> > copying). As long as strings are immutable and references are
> > properly
> > tracked, an implementation can easily share the storage
> > between different
> > strings (except the meta data). I would bet that such an
> > implementation is in
> > the end a lot more efficient than any implementation based on
> > mutability,
> > such as imposed by the dataAccess string interface.
>
> Among other good reasons for encouraging implementations
> based on non-contiguous fixed sized memory management!

A functional string object class can never implement your streamWrite 
interface. As soon as you allow even one method that changes the data 
content, you can no longer share data between different objects. This 
annihilates almost all the advantages of the functional string (object) 
model.

Ben


References:
RE: memory management Jeff Hill

Navigate by Date:
Prev: RE: memory management Jeff Hill
Next: RE: memory management Jeff Hill
Index: 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: RE: memory management Jeff Hill
Next: Base V4 Database: Alarms for analog type records Ralph Lange
Index: 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Feb 2012 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·