Boost logo

Boost :

Subject: Re: [boost] boost.lockfree update
From: Christian Holmquist (c.holmquist_at_[hidden])
Date: 2010-07-23 20:53:33


>
> >> > bool enqueue(T const & t);
> >> > Shouldn't this function throw an exception if t cannot be enqueued?
> >>
> >> i would prefer not to throw an exception! if a constant-size freelist is
> >> used, the enqueue operation may fail, although no `error' occurred. i
> >> prefer
> >> this interface
> >>
> >>
> >>
> > If memory for the operation cannot be obtained, I believe common practice
> > is to throw an exception. IMO, it does not matter if a fixed size pool is
> > exhausted or the global heap, since the effect is the same -> a no op.
> > With current interface I'd need to always check return value for every
> > enqueue for out of memory conditions, something I don't need to do with
> > any other container.
>
> true ... but if you use the fixed-size memory pool, you would have to add a
> try/catch block ...
>

If I can do something about the error, then yes, I would -always- need to
add a try/catch block, since the global heap may be exhausted just as the
fixed-size memory pool can. What I am trying to say, is that I'd prefer the
same semantic of enqueue(T const&) as any std::container::insert(T const&).

std::vector<int> vec;
vec.push_back(1); // may throw
fifo<int> fifo;
fifo.enqueue(1); // may throw

With current interface, I'd need to do something like
if(!fifo.enqueue(1))
{
  throw std::bad_alloc(); // Or something
}

I think the semantic's should be equal to that of std::containers, when
possible. How about a compromise:

void enqueue(const T&) throw(...)
void try_enqueue(const T&) // no throw guarantee if T's copy constructor is
no throw guarantee

For reference, it might be a good idea to have a look at Intel's TBB
concurrent_queue/vector and see what design decisions they've made. I've no
practical use of TBB unfortunately, but I've studied it a bit in order to
make a recommendation for my employer.
Reference is here: TBB
Reference<http://www.threadingbuildingblocks.org/uploads/81/91/Latest%20Open%20Source%20Documentation/Reference.pdf>

> >>
> >> Would if suffice to add another constructor for that?
> > template<class Iterator>
> > fifo(Iterator first, Iterator last)
> >
> > Then you can have an optimized way of populating the lockfree
> > container,without adding unsafe member functions.
>
> for my most important use case, this would not be sufficient. during some
> times, i am accessing my fifos from a single thread only, during other
> times
> by multiple threads ...
>
> It would be interesting if you could add some performance benchmarks
between lockfree vs non-lockfree.

Slightly unrelated:
Have you considered proposing your lockfree algorithms and datastructures as
part of boost::intrusive? To me, using intrusive datastructures would be
preferable in performance critical scenarios, and it's an excellent way of
guaranteeing a non-throwing/non-failing enqueue operation (since the user
can avoid the copy constructor all-together). A higher-level container such
as the current lockfree:fifo could then be built upon such a foundation.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk