When thinking about testability and modular code, I recently thought about whether I should split out the synchronization part of a class from the actual behavior part.
By example:
The app “needs” this:
class Mogrifier { // Mogrifier accesses are thread safe
private:
unsigned int m_state;
mutex m_sync;
public:
Mogrifier()
: m_state(0)
{ }
unsigned int Mutate() {
lock_guard<mutex> lock(m_sync);
const unsigned int old = m_state;
m_state += 42;
return old;
}
:::
};
Seems simple enough, except that locking and the actual stuff the class does aren’t really related.
So I though about whether it’s a good idea to split this up:
class Mogrifier { // Mogrifier is *not* synchronized
private:
unsigned int m_state;
public:
Mogrifier()
: m_state(0)
{ }
unsigned int Mutate() {
const unsigned int old = m_state;
m_state += 42;
return old;
}
:::
};
class SyncedMogrifer {
private:
mutex m_sync;
Mogrifier m_;
public:
unsigned int Mutate() {
lock_guard<mutex> lock(m_sync);
return m_.Mutate();
}
};
- Would you do this?
- Will it help with unit testing?
- I’m awful with Pattern names … what is it called?
- Is there a simple way to “generate” such a wrapper in C++ for an arbitrary calls?
You really need some assistance from Herb. He can tell you how to deal with this. Cliffnotes:
template<typename T> class Monitor {
T t;
std::mutex m;
public:
template<typename F> auto operator()(F&& f) -> decltype(f(t)) {
lock_guard<mutex> lock(m);
return f(t);
}
};
Monitor<Mogrifier> safe;
safe([](Mogrifier& m) {
m.mutate();
});
The second part is that you really shouldn’t block, and if you do, you can’t do it on a per-method level.
5
I would do this if I had other classes that I wanted to synchronise. If I didn’t then I would argue that it’s needless complexity and the synchronised mogrifier looks good to me as it is.
It will help with unit testing if you want to test your synchronise code separate from the Mogrifier functionality, and vice verse. If not then it won’t. Probably a good idea to unit test your synchronisation code as it’s very easy to stuff up.
As for the last two questions… dunno 🙂
(Oh and BTW I’m Australian so I’m going to be bloody minded and spell synchronise with a S and not a Z even though chrome has highlighted all 5 instances of it in this textarea.)
0