Signal Vector
SV介绍
本工程使用C++11实现的轻量级信号与槽功能,用于在实际编程中的代码解耦。
工程代码仅由 sv.hpp ,实际工程源码在200行左右,通俗易懂。
SV使用
1.信号的定义:
sv<参数> 信号名称; /// 信号参数不支持左值引用
2.槽函数
成员函数
全局函数
匿名函数
3.信号与槽的关联
connect(信号发送者,信号,信号接收者,槽函数,同步/异步);
connect(信号发送者,信号,槽函数,同步/异步);
4.信号发送
emit 信号(参数);
5.断开所有信号
disconnect(信号发送者,信号);
6.断开单个信号
由于很少会使用,已删除单个信号的断开;
注意:信号与槽的参数类型必须严格匹配,否则不能连接成功
示例:
#include "sv.hpp"
class Server
{
signals: /// 如果是Qt工程中使用,则需要将signals改成public,因为与Qt的signals关键字冲突
sv<const Student&,int> dataChanged; /// 定义两个参数的dataChanged信号,等价于Qt的void dataChanged(const Student&,int)
sv<const std::string&> newConnection; /// 定义带一个参数的newConnection信号,等价于Qt的 void newConnection(const std::string&)
sv<> finished; /// 定义无参finished信号,等价于Qt的 void finished();
public:
/// 其他属性或函数
}
class Client
{
public slots:
void onServerFinished()
{
/*处理工作*/
}
void onNewConnection(const std::string&)
{
/*处理工作*/
}
void onDataChanged(const Student&,int)
{
/*处理工作*/
}
}
class Application
{
Server server;
Client client;
public:
Application()
{
Sv::connect(&server,&Server ::dataChanged,&client,&Client::onDataChanged);
Sv::connect(&server,&Server::finished,&client,&Client::onServerFinished,Sv::QueuedConnection); /// 异步调用,默认为Sv::DirectConnection同步调用
/*其他信号与槽的关联*/
}
~Application()
{
SvQueue::exec(); /// 等待线程正常退出,必须在程序结束前调用
}
void run()
{
/// 信号发送
emit dataChanged(参数...);
emit newConnection(参数...);
emit finished();
}
}
int main(int argc,char* argv[])
{
Application app;
app.run();
return 0;
}
Signal Vector源码
#ifndef SV_HPP
#define SV_HPP
/*************************************WRITE BY LJX*****************************************/
#include <vector>
#include <thread>
#include <deque>
#include <mutex>
#include <functional>
#include <condition_variable>
#ifndef slots
#define slots
#endif
#ifndef signals
#define signals public
#endif
#ifndef emit
#define emit
#endif
/// 命名空间 Sv
#ifndef SV_NAMESPACE
#define SV_NAMESPACE Sv
#endif
namespace SV_NAMESPACE{
enum Connected{ DirectConnection,QueuedConnection };
template<unsigned int Size> struct SvImp;
template<> struct SvImp<0>{
template<typename Sender,typename Signal,typename Receiver,typename Slot>
static inline void imp(Sender* sender,Signal signal,Receiver* receiver,Slot slot,Connected t = DirectConnection)
{
(sender->*signal).push_back({t,std::bind(std::forward<Slot>(slot),receiver)});
}
/// 支持匿名函数
template<typename Sender,typename Signal,typename Receiver,typename Slot>
static inline void imp(Sender* sender,Signal signal,Slot&& slot,Connected t = DirectConnection)
{
(sender->*signal).push_back({t,std::bind(std::forward<Slot>(slot))});
}
/// 支持全局函数
template<typename Sender,typename Signal,typename Slot>
static inline void imp(Sender* sender,Signal signal,Slot* slot,Connected t = DirectConnection)
{
(sender->*signal).push_back({t,std::bind(slot)});
}
};
#define GENERATOR(size,...)\
template<> struct SvImp<size>{\
template<typename Sender,typename Signal,typename Receiver,typename Slot>\
static inline void imp(Sender* sender,Signal signal,Receiver* receiver,Slot slot,Connected t = DirectConnection)\
{\
using namespace std::placeholders;\
(sender->*signal).push_back({t,std::bind(std::forward<Slot>(slot),receiver,__VA_ARGS__)});\
}\
template<typename Sender,typename Signal,typename Slot>\
static inline void imp(Sender* sender,Signal signal,Slot&& slot,Connected t = DirectConnection)\
{\
using namespace std::placeholders;\
(sender->*signal).push_back({t,std::bind(std::forward<Slot>(slot),__VA_ARGS__)});\
}\
template<typename Sender,typename Signal,typename Slot>\
static inline void imp(Sender* sender,Signal signal,Slot* slot,Connected t = DirectConnection)\
{\
using namespace std::placeholders;\
(sender->*signal).push_back({t,std::bind(slot,__VA_ARGS__)});\
}\
};
GENERATOR(1,_1)
GENERATOR(2,_1,_2)
GENERATOR(3,_1,_2,_3)
GENERATOR(4,_1,_2,_3,_4)
GENERATOR(5,_1,_2,_3,_4,_5)
GENERATOR(6,_1,_2,_3,_4,_5,_6)
GENERATOR(7,_1,_2,_3,_4,_5,_6,_7)
GENERATOR(8,_1,_2,_3,_4,_5,_6,_7,_8)
GENERATOR(9,_1,_2,_3,_4,_5,_6,_7,_8,_9)
GENERATOR(10,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10)
GENERATOR(11,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11)
GENERATOR(12,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12)
GENERATOR(13,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13)
GENERATOR(14,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14)
GENERATOR(15,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15)
GENERATOR(16,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_14,_16)
GENERATOR(17,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17)
GENERATOR(18,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18)
GENERATOR(19,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19)
GENERATOR(20,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20)
GENERATOR(21,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21)
GENERATOR(22,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22)
GENERATOR(23,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23)
GENERATOR(24,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24)
GENERATOR(25,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25)
GENERATOR(26,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26)
GENERATOR(27,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27)
GENERATOR(28,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28)
GENERATOR(29,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29)
#undef GENERATOR
template<typename Sender,typename Signal,typename Receiver,typename Slot>
inline void connect(Sender* sender,Signal signal,Receiver* receiver,Slot slot,Connected t = DirectConnection)
{
SvImp<(sender->*signal).Parmers>::imp(sender,std::forward<Signal>(signal),receiver,std::forward<Slot>(slot),t);
}
/// 支持匿名函数
template<typename Sender,typename Signal,typename Slot>
inline void connect(Sender* sender,Signal signal,Slot&& slot,Connected t = DirectConnection)
{
SvImp<(sender->*signal).Parmers>::imp(sender,std::forward<Signal>(signal),std::forward<Slot>(slot),t);
}
/// 支持全局函数
template<typename Sender,typename Signal,typename Slot>
inline void connect(Sender* sender,Signal signal,Slot* slot,Connected t = DirectConnection)
{
SvImp<(sender->*signal).Parmers>::imp(sender,std::forward<Signal>(signal),slot,t);
}
template<typename Sender,typename Signal>
inline void disconnect(Sender* sender,Signal signal)
{
(sender->*signal).clear();
}
}
class SvQueue
{
using Tp = std::function<void()>;
using Locker = std::unique_lock<std::mutex>;
bool flag;
bool terminal;
std::mutex mutex;
std::condition_variable cv;
std::thread thread;
std::deque<Tp> queue;
public:
static SvQueue& instance()
{
static SvQueue svQueue;
return svQueue;
}
static void exec()
{
SvQueue::instance().wait();
}
public:
void enqueue(Tp tp)
{
Locker locker(mutex);
queue.push_back(tp);
cv.notify_one();
}
Tp dequeue()
{
Locker locker(mutex);
Tp tp = queue.front();
queue.pop_front();
return tp;
}
protected:
SvQueue()
{
flag = true;
terminal = true;
thread = std::thread(&SvQueue::run,this);
}
~SvQueue()
{
wait();
}
protected:
void wait()
{
flag = false;
cv.notify_one();
if(thread.joinable()){
thread.join();
}
}
void terminate()
{
terminal = false;
wait();
}
protected:
void run()
{
while (terminal)
{
{
Locker locker(mutex);
cv.wait(locker, [this]{ return !queue.empty() || !flag; });
if(queue.size() == 0){
if(flag == false){
break;
}else{
continue;
}
}
}
Tp tp = dequeue();
tp();
}
}
};
template<typename... Args>
class sv : protected std::vector<std::pair<char,std::function<void(Args...)>>>
{
using Tp = std::pair<char,std::function<void(Args...)>>;
using Base = std::vector<Tp>;
static constexpr unsigned int Parmers = sizeof...(Args);
template<unsigned int Size> friend struct SV_NAMESPACE::SvImp;
template<typename Sender,typename Signal,typename Receiver,typename Slot>
friend void SV_NAMESPACE::connect(Sender* sender,Signal signal,Receiver* receiver,Slot slot,SV_NAMESPACE::Connected t);
template<typename Sender,typename Signal,typename Slot>
friend void SV_NAMESPACE::connect(Sender* sender,Signal signal,Slot&& slot,SV_NAMESPACE::Connected t);
template<typename Sender,typename Signal,typename Slot>
friend void SV_NAMESPACE::connect(Sender* sender,Signal signal,Slot* slot,SV_NAMESPACE::Connected t);
template<typename Sender,typename Signal>
friend void SV_NAMESPACE::disconnect(Sender* sender,Signal signal);
using Locker = std::unique_lock<std::mutex>;
std::mutex mutex;
public:
template<typename... Params>
inline void operator()(Params&&... parmers)
{
Locker locker(mutex);
typename Base::const_iterator it = this->begin();
typename Base::const_iterator end = this->end();
while(it != end){
switch (it->first)
{
case SV_NAMESPACE::DirectConnection:
it->second(std::forward<Params>(parmers)...);
break;
case SV_NAMESPACE::QueuedConnection:
SvQueue::instance().enqueue([=](){ it->second(parmers...); });
break;
}
++it;
}
}
protected:
sv& operator=(sv&&) = delete;
sv& operator=(const sv&) = delete;
protected:
void clear()
{
Locker locker(mutex);
Base::clear();
}
void push_back(const Tp& tp)
{
Locker locker(mutex);
Base::push_back(tp);
}
void push_back(Tp&& tp)
{
Locker locker(mutex);
Base::push_back(tp);
}
};
#endif // SV_HPP
联系方式
如果有BUG请联系 3111424384@qq.com,欢迎批评指正。