c++ delegate实现
废话不多说,上代码
#pragma once
#include <mutex>
#include <thread>
template<typename T>
class Lockable
{
private:
T _data;
mutable std::recursive_mutex _mutex;
friend class Ptr;
friend class ConstPtr;
public:
struct Ptr
{
Ptr(Lockable* lockable)
: _lockable(lockable)
, _lock(_lockable->_mutex)
{
}
T& operator*()
{
if(_lockable)
{
return _lockable->_data;
}
throw("Attempt to dereference a detached Lockable::Ptr");
}
T* operator->()
{
if(_lockable)
{
return &_lockable->_data;
}
return nullptr;
}
operator bool()
{
return _lockable != nullptr;
}
private:
Lockable* _lockable;
std::unique_lock<std::recursive_mutex> _lock;
};
struct ConstPtr
{
ConstPtr(const Lockable* lockable)
: _lockable(lockable)
, _lock(_lockable->_mutex)
{
}
const T& operator*()
{
if(_lockable)
{
return _lockable->_data;
}
throw("Attempt to dereference a detached Lockable::ConstPtr");
}
const T* operator->()
{
if(_lockable)
{
return &_lockable->_data;
}
return nullptr;
}
operator bool()
{
return _lockable != nullptr;
}
private:
const Lockable* _lockable;
std::unique_lock<std::recursive_mutex> _lock;
};
public:
template<typename... Args>
Lockable(Args... args)
: _data(args...)
{
}
Ptr lock()
{
return std::move(Ptr(this));
}
ConstPtr readLock() const
{
return std::move(ConstPtr(this));
}
};
#pragma once
#include <functional>
#include <vector>
#include "Lockable.hpp"
template<typename Signature>
class Delegate;
template<typename R, typename...Args>
class Delegate<R(Args...)>
{
public:
using Callback = std::function<R(Args...)>;
struct Entry
{
Entry(const Callback& callback)
: _callback([callback](const std::shared_ptr<void>&, Args... args){ callback(args...); })
{}
Entry(const std::shared_ptr<void>& ptr, const Callback& callback)
: _wptr(ptr)
, _callback([callback](const std::shared_ptr<void>&, Args... args){ callback(args...); })
{}
Entry(const std::shared_ptr<void>& ptr, const std::function<void(const std::shared_ptr<void>&, Args...)>& callback)
: _wptr(ptr)
, _callback(callback)
{}
std::weak_ptr<void> _wptr;
std::function<void(const std::shared_ptr<void>&, Args...)> _callback;
};
template<typename T>
struct CallbackBuilder
{
CallbackBuilder(Delegate* delegate, std::shared_ptr<T> instance)
: _delegate(delegate)
, _instancePtr(instance)
{
}
void operator,(void (T::*mFunc)(Args...))
{
_delegate->addEntry(Entry(_instancePtr, [mFunc](const std::shared_ptr<void>& ptr, Args... args){
if(auto instancePtr = *(std::shared_ptr<T>*)(&ptr))
{
((*instancePtr).*mFunc)(args...);
}
}));
}
void operator,(const Callback& callback)
{
_delegate->addEntry(Entry(_instancePtr, [callback](const std::shared_ptr<void>&, Args... args){
callback(args...);
}));
}
Delegate* _delegate;
std::shared_ptr<T> _instancePtr;
};
public:
void addEntry(const Entry& entry)
{
if(auto entries = _entries.lock())
{
entries->emplace_back(entry);
}
}
void operator()(Args... args) const
{
for(auto& entry : *(_entries.readLock()))
{
entry._callback(entry._wptr.lock(), args...);
}
}
Delegate& operator+=(const Callback& callback)
{
addEntry(Entry(callback));
return *this;
}
Delegate& operator+=(void(*func)(Args...))
{
addEntry(Entry(Callback(func)));
return *this;
}
template<typename T>
CallbackBuilder<T> operator+=(T* instance)
{
return CallbackBuilder<T>(this, instance->shared_from_this());
}
template<typename T>
CallbackBuilder<T> operator+=(const std::shared_ptr<T>& instance)
{
return CallbackBuilder<T>(this, instance);
}
protected:
mutable Lockable<std::vector<Entry>> _entries;
};