1 // SignalSlot.h: interface for the CSignalSlot class.
2 //
3 //////////////////////////////////////////////////////////////////////
4
5 #if !defined(AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_)
6 #define AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_
7
8 #include <Afxtempl.h>
9
10 #if _MSC_VER > 1000
11 #pragma once
12 #endif // _MSC_VER > 1000
13
14 // 15 // 16
17 //--------------------------------------------------------------------------------------------
18 // 静态slot接口函数类型指针定义
19 typedef int (__cdecl *SS_STAIC_SLOTFUNC)(void *pSelf,int slot_F,void *pSrc,void *pDes);
20
21 // 数据结构定义
22 struct FuncItem
23 {
24 bool is_use; //是否使用
25 int signal_F;
26 int slot_F;
27 };
28
29 struct SSItem
30 {
31 bool is_use; //是否使用
32
33 void* signal_pSelf;
34 void* slot_pSelf;
35
36 void* slot_pFunc;
37 CArray<FuncItem,FuncItem>*pFuncArray;
38 };
39
40 //----------------------------------------------------------------------------------------------------------------------
41 /*
42 宏定义1: 信号槽类注册
43 说明: 信号槽(接收方)类定义需要使用该宏声明
44 在类定义最开始位置声明,结尾不需要冒号。例子如下所示:
45 class CTest
46 {
47 SS_REGISTER(CTest)
48 public:
49 ...
50 }
51
52 参数: ClassName 为类名称
53 宏展开: 定义了一个公有静态函数:
54 SS_STATIC_SLOT: 函数名称
55 pSelf: 类对象指针
56 slot_F: 槽函数ID (成员函数指针转换得到)
57 pSrc: 信号发送方输入参数void通用指针
58 pDes: 返回参数内存指针(由调用方提供)
59 */
60 #define SS_REGISTER(ClassName) \
61 public: static int _SS_STATIC_SLOT_(void *pSelf,int slot_F,void *pSrc,void *pDes)\
62 {\
63 typedef int(ClassName::*SLOTFUNC)(void*pSrc,void*pDes=NULL);\
64 SLOTFUNC slot_Func;\
65 int TEMP = (int)(&slot_Func);\
66 *((int*)(TEMP)) = slot_F;\
67 int res = (((ClassName*)(pSelf))->*slot_Func)(pSrc,pDes);\
68 return res;\
69 }
70
71 // 宏定义2: 信号函数定义
72 #define SS_SIGNAL(ClassName,FuncName) \
73 int FuncName(void*pSrc,void*pDes=NULL)\
74 {\
75 typedef int(ClassName::*SLOTFUNC)(void*,void*);\
76 SLOTFUNC pfunc = &ClassName::FuncName;\
77 int funcID = *((int*)((int)(&pfunc)));\
78 return CSignalSlot::SignalSS(this,funcID,pSrc,pDes);\
79 }
80
81 // 宏定义3: 初始化连接
82 #define SS_INITE(signalSelf,slotSelf,res) \
83 *res = CSignalSlot::IniteSS(signalSelf,slotSelf,(slotSelf)->_SS_STATIC_SLOT_);
84
85 // 宏定义4: 解除对象连接
86 #define SS_CLOSE(signalSelf,slotSelf,res) \
87 *res = CSignalSlot::CloseSS(signalSelf,slotSelf);
88
89 // 宏定义5: 连接功能函数
90 #define SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) \
91 {\
92 typedef int(signalClassName::*SIGNAL_PF)(void*,void*);\
93 typedef int(slotClassName::*SLOT_PF)(void*,void*);\
94 SIGNAL_PF Signal_F = &signalClassName::signalFunc;\
95 SLOT_PF slot_F = &slotClassName::slotFunc;\
96 *res = CSignalSlot::ConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F))));\
97 }
98
99 // 宏定义6: 断开功能连接
100 #define SS_DISCONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) \
101 {\
102 typedef int(signalClassName::*SIGNAL_PF)(void*,void*);\
103 typedef int(slotClassName::*SLOT_PF)(void*,void*);\
104 SIGNAL_PF Signal_F = &signalClassName::signalFunc;\
105 SLOT_PF slot_F = &slotClassName::slotFunc;\
106 *res = CSignalSlot::DisConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F))));\
107 }
108
109 // 宏定义7: 初始化连接(3与5的功能组合)
110 #define SS_INICONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) \
111 SS_INITE(signalSelf,slotSelf,res)\
112 if(*res!=-1)\
113 SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res);
114 //------------------------------------------------------------------------------------------------------------------------------
115
116 class CSignalSlot
117 {
118 public:
119 static int DisConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F);
120 static int CloseSS(void *signal_pSelf,void*slot_pSelf);
121 static int IniteSS(void* signal_pSelf,void* slot_pSelf,SS_STAIC_SLOTFUNC slot_pFunc);
122 static int SignalSS(void *signal_pSelf,int signal_F,void *pSrc,void *pDes=NULL);
123 static int ConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F);
124 CSignalSlot();
125 virtual ~CSignalSlot();
126 private:
127 static void CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray);
128 static CArray<SSItem,SSItem>m_SSArray;
129 static int m_loopback;
130 };
131
132 #endif // !defined(AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_)
1 // SignalSlot.cpp: implementation of the CSignalSlot class.
2 //
3 //////////////////////////////////////////////////////////////////////
4
5 #include "stdafx.h"
6 #include "SignalSlot.h"
7
8 #ifdef _DEBUG
9 #undef THIS_FILE
10 static char THIS_FILE[]=__FILE__;
11 #define new DEBUG_NEW
12 #endif
13
14 //////////////////////////////////////////////////////////////////////
15 // Construction/Destruction
16 //////////////////////////////////////////////////////////////////////
17 CArray<SSItem,SSItem> CSignalSlot::m_SSArray;
18 int CSignalSlot::m_loopback = 0;
19
20 CSignalSlot::CSignalSlot()
21 {
22
23 }
24
25 CSignalSlot::~CSignalSlot()
26 {
27
28 }
29
30 //初始化对象连接 建立非对称连接 signal对象可以往slot对象发消息 一条单向通信链路定义为一个连接项
31 // 返回值:1 成功 0 已存在该连接 -1 添加失败
32 int CSignalSlot::IniteSS(void* signal_pSelf,void* slot_pSelf,SS_STAIC_SLOTFUNC slot_pFunc)
33 {
34 int len = CSignalSlot::m_SSArray.GetSize();
35 SSItem tItem;
36 int nPos = -1;
37 // 扫描是否已存在该连接(同时记录下第一个位置内存项记录)
38 for(int i=0;i<len;i++)
39 {
40 tItem = CSignalSlot::m_SSArray.GetAt(i);
41 if(true==tItem.is_use)
42 {
43 if(signal_pSelf==tItem.signal_pSelf && slot_pSelf==tItem.slot_pSelf)
44 {
45 return 0; // 已存在该连接
46 }
47 }
48 else
49 {
50 if(-1==nPos)
51 {
52 nPos = i;// 记住第一个扫描到的位置用内存项位置
53 }
54 }
55 }
56
57 //增加新连接
58 if(nPos!=-1)// 占用空闲位置项
59 {
60 tItem = CSignalSlot::m_SSArray.GetAt(nPos);
61 tItem.is_use = TRUE;
62 tItem.signal_pSelf = signal_pSelf;
63 tItem.slot_pSelf = slot_pSelf;
64 tItem.slot_pFunc = slot_pFunc;
65
66 CSignalSlot::m_SSArray.SetAt(nPos,tItem);
67 return 1;
68 }else //新增位置项
69 {
70 tItem.is_use = TRUE;
71 tItem.signal_pSelf = signal_pSelf;
72 tItem.slot_pSelf = slot_pSelf;
73 tItem.slot_pFunc = slot_pFunc;
74 tItem.pFuncArray = new CArray<FuncItem,FuncItem>;
75 CSignalSlot::m_SSArray.Add(tItem);
76 return 1;
77 }
78 }
79
80 // 信号|槽连接: <signal对象+成员函数ID,slot对象+成员函数>作为一个连接项
81 // 返回值:1:成功 0:已存在该连接项 -1:添加失败
82 int CSignalSlot::ConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F)
83 {
84 int len = CSignalSlot::m_SSArray.GetSize();
85 SSItem sItem;
86 FuncItem fItem;
87 int nPos = -1;
88 for (int i=0;i<len;i++)
89 {
90 sItem = CSignalSlot::m_SSArray.GetAt(i);
91 if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf && true==sItem.is_use)
92 {
93 int sum = sItem.pFuncArray->GetSize();
94 for(int k=0;k<sum;k++)
95 {
96 fItem= sItem.pFuncArray->GetAt(k);
97 if(true==fItem.is_use)
98 {
99 if(signal_F==fItem.signal_F && slot_F==fItem.slot_F)
100 {
101 return 0; //已存在该连接
102 }
103 }else
104 {
105 if(-1==nPos)
106 {
107 nPos = k;
108 }
109 }
110 }
111 // 新增连接
112 fItem.is_use = true;
113 fItem.signal_F = signal_F;
114 fItem.slot_F = slot_F;
115 if(nPos!=-1)
116 {
117 sItem.pFuncArray->SetAt(nPos,fItem);
118 return 1;
119 }else
120 {
121 sItem.pFuncArray->Add(fItem);
122 return 1;
123 }
124 }
125 }
126
127 return -1; // 对象连接没有初始化
128 }
129
130 // 返回值: 调用槽的执行数目(每调用一个槽函数,返回值加1)
131 int CSignalSlot::SignalSS(void *signal_pSelf,int signal_F,void *pSrc, void *pDes)
132 {
133 int res = 0;
134 int len = CSignalSlot::m_SSArray.GetSize();
135 for(int i=0;i<len;i++)
136 {
137 SSItem ssitem = CSignalSlot::m_SSArray.GetAt(i);
138 if(ssitem.is_use == true && signal_pSelf==ssitem.signal_pSelf) //找到对象连接
139 {
140 int sum = ssitem.pFuncArray->GetSize();
141 for(int k=0;k<sum;k++)
142 {
143 FuncItem fitem = ssitem.pFuncArray->GetAt(k);
144 if(fitem.is_use==true && signal_F==fitem.signal_F) //找到信号|槽连接
145 {
146 ////////////////////////////////////////////////////////////////////////////
147 if(CSignalSlot::m_loopback>0) //判断是否出现回环(避免信号函数的嵌套调用)
148 {
149 CSignalSlot::m_loopback = 0; //清除嵌套计数
150 return 0; // 中断返回
151 }
152 CSignalSlot::m_loopback += 1;
153 /////////////////////////////////////////////////////////////////////////////
154
155 SS_STAIC_SLOTFUNC tempFunc = (SS_STAIC_SLOTFUNC)ssitem.slot_pFunc;
156 tempFunc(ssitem.slot_pSelf,fitem.slot_F,pSrc,pDes); //通过静态槽接口函数发起调用
157 res+=1;
158 }
159 }
160 }
161 }
162
163 CSignalSlot::m_loopback=0; //清除嵌套计数
164 return res;
165 }
166
167 // 关闭删除对象连接(单向)
168 // 返回值:>0 成功 0 已不存在该连接 -1 删除失败
169 int CSignalSlot::CloseSS(void *signal_pSelf, void *slot_pSelf)
170 {
171 int len = CSignalSlot::m_SSArray.GetSize();
172 SSItem sItem;
173 int res = 0;
174 for(int i=0;i<len;i++)
175 {
176 sItem = CSignalSlot::m_SSArray.GetAt(i);
177 if(false==sItem.is_use)
178 {
179 continue;
180 }
181 if(NULL==signal_pSelf)
182 {
183 if(slot_pSelf==sItem.slot_pSelf)
184 {
185 sItem.is_use = false;
186 CSignalSlot::CloseFuncArray(sItem.pFuncArray);
187 res+=1;
188 }
189 }else if(NULL==slot_pSelf)
190 {
191 if(signal_pSelf==sItem.signal_pSelf)
192 {
193 sItem.is_use = false;
194 CSignalSlot::CloseFuncArray(sItem.pFuncArray);
195 res+=1;
196 }
197 }else if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf)
198 {
199 sItem.is_use = false;
200 CSignalSlot::CloseFuncArray(sItem.pFuncArray);
201 res+=1;
202 break;
203 }
204 }
205 return res;
206 }
207
208
209 // 删除信号槽连接
210 // 返回值:1 成功 0 已不存在该连接 -1 删除失败
211 int CSignalSlot::DisConnectSS(void *signal_pSelf, int signal_F, void *slot_pSelf, int slot_F)
212 {
213 int len = CSignalSlot::m_SSArray.GetSize();
214 SSItem sItem;
215 for (int i=0;i<len;i++)
216 {
217 sItem = CSignalSlot::m_SSArray.GetAt(i);
218 if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf &&true==sItem.is_use)
219 {
220 int sum = sItem.pFuncArray->GetSize();
221 FuncItem item;
222 for(int k=0;k<sum;k++)
223 {
224 item = sItem.pFuncArray->GetAt(k);
225 if(signal_F==item.signal_F && slot_F==item.slot_F)
226 {
227 item = sItem.pFuncArray->GetAt(k);
228 item.is_use = false;
229 sItem.pFuncArray->SetAt(k,item);
230 return 1; //删除连接
231 }
232 }
233 }
234 }
235
236 return 0; // 对象连接没有初始化
237 }
238
239
240 void CSignalSlot::CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray)
241 {
242 int sum = pFuncArray->GetSize();
243 FuncItem item;
244 for(int k=0;k<sum;k++)
245 {
246 item = pFuncArray->GetAt(k);
247 item.is_use = false;
248 pFuncArray->SetAt(k,item);
249 }
250 }