C++ 对象间通讯机制 框架实现

  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 }


 
原文地址:https://www.cnblogs.com/Esperanto/p/5179505.html