In Java, there is an Exchanger class (http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Exchanger.html). How to implement something like that in C++ (using boost)
A:
The best thing to do is to understand an implementation in Java itself and try to re-implement it using boost threading classes.
Vijay Mathew
2010-07-09 05:55:13
A:
Okay, here's my second attempt that cleans up the race condition. There is an inefficiency when more then two threads try to use a single exchanger object but since that is such an edge case, I think we can live with that:
#include <boost/thread.hpp>
template <class T>
class exchanger
{
public:
exchanger()
: ptr(0),
state(EMPTY)
{
}
void exchange(T &t)
{
boost::unique_lock<boost::mutex> lock(m);
// If we arrive while an actual exchange has
// started but has not finished, keep out of
// the way.
while (state == SECOND_ARRIVED)
{
cv_overflow.wait(lock);
}
assert((state == EMPTY) || (state == FIRST_ARRIVED));
switch (state)
{
case EMPTY:
assert(!ptr);
ptr = &t;
state = FIRST_ARRIVED;
while (state == FIRST_ARRIVED)
{
cv_main.wait(lock);
}
assert(state == SECOND_ARRIVED);
ptr = 0;
state = EMPTY;
// Wake up any threads that happened to get
// the mutex after the other side of the
// exchanger notified us but before we woke up.
cv_overflow.notify_all();
break;
case FIRST_ARRIVED:
assert(ptr);
state = SECOND_ARRIVED;
using std::swap;
swap(t, *ptr);
cv_main.notify_one();
break;
}
}
private:
boost::mutex m;
boost::condition_variable cv_main;
boost::condition_variable cv_overflow;
T *ptr;
enum { EMPTY, FIRST_ARRIVED, SECOND_ARRIVED } state;
};
R Samuel Klatchko
2010-07-09 06:39:57
@R: is "mut" meant to be "m"?
dman
2010-07-09 07:10:46
@dman - yes; thanks for catching that.
R Samuel Klatchko
2010-07-09 16:13:53