Extract AutoRegister logic to a helper class

This commit is contained in:
Maxime Coste 2013-04-02 13:56:30 +02:00
parent b266035c71
commit a18241a03b
2 changed files with 75 additions and 47 deletions

View File

@ -244,57 +244,28 @@ constexpr Buffer::Flags operator~(Buffer::Flags lhs)
return (Buffer::Flags)(~(int)lhs);
}
class BufferChangeListener_AutoRegister : public BufferChangeListener
struct BufferListenerRegisterFuncs
{
static void insert(const Buffer& buffer, BufferChangeListener& listener)
{
buffer.change_listeners().insert(&listener);
}
static void remove(const Buffer& buffer, BufferChangeListener& listener)
{
buffer.change_listeners().erase(&listener);
}
};
class BufferChangeListener_AutoRegister
: public BufferChangeListener,
public AutoRegister<BufferChangeListener_AutoRegister,
BufferListenerRegisterFuncs, const Buffer>
{
public:
BufferChangeListener_AutoRegister(const Buffer& buffer)
: m_buffer(&buffer)
{
m_buffer->change_listeners().insert(this);
}
: AutoRegister(buffer) {}
BufferChangeListener_AutoRegister(const BufferChangeListener_AutoRegister& other)
: m_buffer(other.m_buffer)
{
m_buffer->change_listeners().insert(this);
}
BufferChangeListener_AutoRegister(BufferChangeListener_AutoRegister&& other)
: m_buffer(other.m_buffer)
{
m_buffer->change_listeners().insert(this);
}
~BufferChangeListener_AutoRegister()
{
m_buffer->change_listeners().erase(this);
}
BufferChangeListener_AutoRegister& operator=(const BufferChangeListener_AutoRegister& other)
{
if (m_buffer != other.m_buffer)
{
m_buffer->change_listeners().erase(this);
m_buffer = other.m_buffer;
m_buffer->change_listeners().insert(this);
}
return *this;
}
BufferChangeListener_AutoRegister& operator=(BufferChangeListener_AutoRegister&& other)
{
if (m_buffer != other.m_buffer)
{
m_buffer->change_listeners().erase(this);
m_buffer = other.m_buffer;
m_buffer->change_listeners().insert(this);
}
return *this;
}
const Buffer& buffer() const { return *m_buffer; }
private:
const Buffer* m_buffer;
const Buffer& buffer() const { return registry(); }
};
}

View File

@ -227,6 +227,63 @@ const T& clamp(const T& val, const T& min, const T& max)
return (val < min ? min : (val > max ? max : val));
}
// *** AutoRegister: RAII handling of value semantics registering classes ***
template<typename EffectiveType, typename RegisterFuncs, typename Registry>
class AutoRegister
{
public:
AutoRegister(Registry& registry)
: m_registry(&registry)
{
RegisterFuncs::insert(*m_registry, effective_this());
}
AutoRegister(const AutoRegister& other)
: m_registry(other.m_registry)
{
RegisterFuncs::insert(*m_registry, effective_this());
}
AutoRegister(AutoRegister&& other)
: m_registry(other.m_registry)
{
RegisterFuncs::insert(*m_registry, effective_this());
}
~AutoRegister()
{
RegisterFuncs::remove(*m_registry, effective_this());
}
AutoRegister& operator=(const AutoRegister& other)
{
if (m_registry != other.m_registry)
{
RegisterFuncs::remove(*m_registry, effective_this());
m_registry = other.m_registry;
RegisterFuncs::insert(*m_registry, effective_this());
}
return *this;
}
AutoRegister& operator=(AutoRegister&& other)
{
if (m_registry != other.m_registry)
{
RegisterFuncs::remove(*m_registry, effective_this());
m_registry = other.m_registry;
RegisterFuncs::insert(*m_registry, effective_this());
}
return *this;
}
Registry& registry() const { return *m_registry; }
private:
EffectiveType& effective_this() { return static_cast<EffectiveType&>(*this); }
Registry* m_registry;
};
}
#endif // utils_hh_INCLUDED