Re: to const or not to const
* Kai-Uwe Bux:
I recently dived into multi-threaded issues. To make my life a little
easier, I decided that it would be nice to have a simple fifo buffer to ease
communications between threads. The interface is this:
template < typename T >
class fifo {
public:
typedef T value_type;
typedef std::size_t size_type
fifo ( size_type n = -1 );
void push ( value_type const & value );
value_type pop ( void );
// blocks until an item is available
This method is very interesting. In a single-threaded program it should clearly
not be the basic interface but just a convenience wrapper around 'top' and
'remove_top', because the copying of value_type may throw after altering the
fifo state, preventing sound exception guarantee. But in a multi-threaded
environment how does one use the more primitive operations safely?
I can imagine that 'top' and 'remove_top' would be accessed within a block
protected by a mutex.
I think that mutex thingy should be exposed as part of the interface, and the
'pop' above an inline convenience method.
bool available ( void ) const;
// returns true if the a call to pop() would not block
void wait_available ( void ); // should this be const ?
// blocks until a call to pop() will not block
Here you're really into that problem but apparently not realizing, or perhaps I
don't understand the intended semantics. After 'available' indicates something
is available, how long is it available? Is there only ever 1 consumer?
};
Typically there are some threads push()ing items into the fifo and one
thread pop()ing items off the buffer and processing them. It is clear that
push() and pop() should not be const: they change the contents of the
buffer. Also, availble() should be const since it just returns a property of
the buffer without modifying it.
But, what about wait_available()? Even though it does not change the buffer
contents by itself, once it returns it effectively signals to the thread
where it was called that another thread has pushed in item. So it marks a
change of the buffer, even though it does not in itself bring that change
about. Should this method be const or not?
The question is rather, should this method be or not? ;-)
Cheers & hth.,
- Alf