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. // 静态slot接口函数类型指针定义
  17. typedef int (__cdecl *SS_STAIC_SLOTFUNC)(void *pSelf,int slot_F,void *pSrc,void *pDes);
  18.  
  19. // 数据结构定义
  20. struct FuncItem
  21. {
  22. bool is_use; //是否使用
  23. int signal_F;
  24. int slot_F;
  25. };
  26.  
  27. struct SSItem
  28. {
  29. bool is_use; //是否使用
  30.  
  31. void* signal_pSelf;
  32. void* slot_pSelf;
  33.  
  34. void* slot_pFunc;
  35. CArray<FuncItem,FuncItem>*pFuncArray;
  36. };
  37.  
  38. //----------------------------------------------------------------------------------------------------------------------
  39. /*
  40. 宏定义1: 信号槽类注册
  41. 说明: 信号槽(接收方)类定义需要使用该宏声明
  42. 在类定义最开始位置声明,结尾不需要冒号。例子如下所示:
  43. class CTest
  44. {
  45. SS_REGISTER(CTest)
  46. public:
  47. ...
  48. }
  49.  
  50. 参数: ClassName 为类名称
  51. 宏展开: 定义了一个公有静态函数:
  52. SS_STATIC_SLOT: 函数名称
  53. pSelf: 类对象指针
  54. slot_F: 槽函数ID (成员函数指针转换得到)
  55. pSrc: 信号发送方输入参数void通用指针
  56. pDes: 返回参数内存指针(由调用方提供)
  57. */
  58. #define SS_REGISTER(ClassName) \
  59. public: static int _SS_STATIC_SLOT_(void *pSelf,int slot_F,void *pSrc,void *pDes)\
  60. {\
  61. typedef int(ClassName::*SLOTFUNC)(void*pSrc,void*pDes=NULL);\
  62. SLOTFUNC slot_Func;\
  63. int TEMP = (int)(&slot_Func);\
  64. *((int*)(TEMP)) = slot_F;\
  65. int res = (((ClassName*)(pSelf))->*slot_Func)(pSrc,pDes);\
  66. return res;\
  67. }
  68.  
  69. // 宏定义2: 信号函数定义
  70. #define SS_SIGNAL(ClassName,FuncName) \
  71. int FuncName(void*pSrc,void*pDes=NULL)\
  72. {\
  73. typedef int(ClassName::*SLOTFUNC)(void*,void*);\
  74. SLOTFUNC pfunc = &ClassName::FuncName;\
  75. int funcID = *((int*)((int)(&pfunc)));\
  76. return CSignalSlot::SignalSS(this,funcID,pSrc,pDes);\
  77. }
  78.  
  79. // 宏定义3: 初始化连接
  80. #define SS_INITE(signalSelf,slotSelf,res) \
  81. *res = CSignalSlot::IniteSS(signalSelf,slotSelf,(slotSelf)->_SS_STATIC_SLOT_);
  82.  
  83. // 宏定义4: 解除对象连接
  84. #define SS_CLOSE(signalSelf,slotSelf,res) \
  85. *res = CSignalSlot::CloseSS(signalSelf,slotSelf);
  86.  
  87. // 宏定义5: 连接功能函数
  88. #define SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) \
  89. {\
  90. typedef int(signalClassName::*SIGNAL_PF)(void*,void*);\
  91. typedef int(slotClassName::*SLOT_PF)(void*,void*);\
  92. SIGNAL_PF Signal_F = &signalClassName::signalFunc;\
  93. SLOT_PF slot_F = &slotClassName::slotFunc;\
  94. *res = CSignalSlot::ConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F))));\
  95. }
  96.  
  97. // 宏定义6: 断开功能连接
  98. #define SS_DISCONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) \
  99. {\
  100. typedef int(signalClassName::*SIGNAL_PF)(void*,void*);\
  101. typedef int(slotClassName::*SLOT_PF)(void*,void*);\
  102. SIGNAL_PF Signal_F = &signalClassName::signalFunc;\
  103. SLOT_PF slot_F = &slotClassName::slotFunc;\
  104. *res = CSignalSlot::DisConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F))));\
  105. }
  106.  
  107. // 宏定义7: 初始化连接(3与5的功能组合)
  108. #define SS_INICONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) \
  109. SS_INITE(signalSelf,slotSelf,res)\
  110. if(*res!=-)\
  111. SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res);
  112. //------------------------------------------------------------------------------------------------------------------------------
  113.  
  114. class CSignalSlot
  115. {
  116. public:
  117. static int DisConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F);
  118. static int CloseSS(void *signal_pSelf,void*slot_pSelf);
  119. static int IniteSS(void* signal_pSelf,void* slot_pSelf,SS_STAIC_SLOTFUNC slot_pFunc);
  120. static int SignalSS(void *signal_pSelf,int signal_F,void *pSrc,void *pDes=NULL);
  121. static int ConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F);
  122. CSignalSlot();
  123. virtual ~CSignalSlot();
  124. private:
  125. static void CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray);
  126. static CArray<SSItem,SSItem>m_SSArray;
  127. static int m_loopback;
  128. };
  129.  
  130. #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 = ;
  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 = -;
  37. // 扫描是否已存在该连接(同时记录下第一个位置内存项记录)
  38. for(int i=;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 ; // 已存在该连接
  46. }
  47. }
  48. else
  49. {
  50. if(-==nPos)
  51. {
  52. nPos = i;// 记住第一个扫描到的位置用内存项位置
  53. }
  54. }
  55. }
  56.  
  57. //增加新连接
  58. if(nPos!=-)// 占用空闲位置项
  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 ;
  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 ;
  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 = -;
  88. for (int i=;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=;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 ; //已存在该连接
  102. }
  103. }else
  104. {
  105. if(-==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!=-)
  116. {
  117. sItem.pFuncArray->SetAt(nPos,fItem);
  118. return ;
  119. }else
  120. {
  121. sItem.pFuncArray->Add(fItem);
  122. return ;
  123. }
  124. }
  125. }
  126.  
  127. return -; // 对象连接没有初始化
  128. }
  129.  
  130. // 返回值: 调用槽的执行数目(每调用一个槽函数,返回值加1)
  131. int CSignalSlot::SignalSS(void *signal_pSelf,int signal_F,void *pSrc, void *pDes)
  132. {
  133. int res = ;
  134. int len = CSignalSlot::m_SSArray.GetSize();
  135. for(int i=;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=;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>) //判断是否出现回环(避免信号函数的嵌套调用)
  148. {
  149. CSignalSlot::m_loopback = ; //清除嵌套计数
  150. return ; // 中断返回
  151. }
  152. CSignalSlot::m_loopback += ;
  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+=;
  158. }
  159. }
  160. }
  161. }
  162.  
  163. CSignalSlot::m_loopback=; //清除嵌套计数
  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 = ;
  174. for(int i=;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+=;
  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+=;
  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+=;
  202. break;
  203. }
  204. }
  205. return res;
  206. }
  207.  
  208. // 删除信号槽连接
  209. // 返回值:1 成功 0 已不存在该连接 -1 删除失败
  210. int CSignalSlot::DisConnectSS(void *signal_pSelf, int signal_F, void *slot_pSelf, int slot_F)
  211. {
  212. int len = CSignalSlot::m_SSArray.GetSize();
  213. SSItem sItem;
  214. for (int i=;i<len;i++)
  215. {
  216. sItem = CSignalSlot::m_SSArray.GetAt(i);
  217. if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf &&true==sItem.is_use)
  218. {
  219. int sum = sItem.pFuncArray->GetSize();
  220. FuncItem item;
  221. for(int k=;k<sum;k++)
  222. {
  223. item = sItem.pFuncArray->GetAt(k);
  224. if(signal_F==item.signal_F && slot_F==item.slot_F)
  225. {
  226. item = sItem.pFuncArray->GetAt(k);
  227. item.is_use = false;
  228. sItem.pFuncArray->SetAt(k,item);
  229. return ; //删除连接
  230. }
  231. }
  232. }
  233. }
  234.  
  235. return ; // 对象连接没有初始化
  236. }
  237.  
  238. void CSignalSlot::CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray)
  239. {
  240. int sum = pFuncArray->GetSize();
  241. FuncItem item;
  242. for(int k=;k<sum;k++)
  243. {
  244. item = pFuncArray->GetAt(k);
  245. item.is_use = false;
  246. pFuncArray->SetAt(k,item);
  247. }
  248. }
  1.  
  1.  

C++ 对象间通讯机制 框架实现的更多相关文章

  1. 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制【转】

    本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder ...

  2. Android Binder 进程间通讯机制梳理

    什么是 Binder ? Binder是Android系统中进程间通讯(IPC)的一种方式,也是Android系统中最重要的特性之一.Binder的设计采用了面向对象的思想,在Binder通信模型的四 ...

  3. 如何才能学到Qt的精髓——信号槽之间的无关性,提供了绝佳的对象间通讯方式,QT的GUI全是自己的一套,并且完全开源,提供了一个绝好机会窥视gui具体实现

    姚冬,中老年程序员 叶韵.KY Xu.赵奋强 等人赞同 被邀请了很久了,一直在思考,今天终于下决心开始写回答. 这个问题的确是够大的,Qt的代码规模在整个开源世界里也是名列前茅的,这么大的项目其中的精 ...

  4. C#进程间通讯或同步的框架引荐

    这篇文章主要介绍了一个进程间通讯同步的C#框架,代码具有相当的稳定性和可维护性,随着.NET的开源也会被注入更多活力,推荐!需要的朋友可以参考下  0.背景简介 微软在 .NET 框架中提供了多种实用 ...

  5. java 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    参考文章:http://ifeve.com/java-concurrency-thread-directory/ 其中的竞态,线程安全,内存模型,线程间的通信,java ThreadLocal类小节部 ...

  6. 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...

  7. android 进程间通信 messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯? android 消息机制 进程间 android 进程间 可以用 handler么 messenger 与 handler 机制 messenger 机制 是不是 就是 handler 机制 或 , 是不是就是 消息机制 android messenge

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯 ...

  8. ACE框架 基于共享内存的进程间通讯

    ACE框架将基于共享内存的进程间通讯功能,如其它IO组件或IPC组件一样,设计成三个组件.流操作组件ACE_MEM_Stream,连接器组件ACE_MEM_Connector,以及接收连接组件ACE_ ...

  9. Node.js - 阿里Egg的多进程模型和进程间通讯

    前言 最近用Egg作为底层框架开发项目,好奇其多进程模型的管理实现,于是学习了解了一些东西,顺便记录下来.文章如有错误, 请轻喷 为什么需要多进程 伴随科技的发展, 现在的服务器基本上都是多核cpu的 ...

随机推荐

  1. call 和 apply的定义和区别?

    1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call ...

  2. 004 gcc 编译 C/C++ 默认使用哪个标准

    0. 前言 我挺久没碰 C,不想就这么忘了,最近重温了一些相关知识 1. C 语言的几种"方言" 简单地说,有这么几种常见的 年份 名称 1983 ANSI C 1987 C87 ...

  3. Struts学习(一)

    1.Struts开发基础 1.1  MVC的基本概念 mvc将一个应用系统的输入.处理和输出流程按照Model(模型).View(视图)和Controller(控制器)三部分进行分离,划分成模型层.视 ...

  4. Codeforces 1255E Send Boxes to Alice(前缀和+枚举+数论)

    我们考虑前缀和sum[i],如果将a[i+1]中的一个塞入a[i]中,则不影响sum[i+1],但是sum[i]++,如果将a[i]中的一个塞入a[i+1],则不影响sum[i+1],但是sum[i] ...

  5. php-redis的配置与使用

    从此处下载 https://codeload.github.com/phpredis/phpredis/zip/develop 也就php-redis的安装包,在zip格式,在windows下解压,将 ...

  6. thinkphp5 验证码出不来的常见问题

    对于thinkphp如何实现验证码,我这里就不介绍了.直接看之前的文章 http://www.cnblogs.com/qqblog/p/6639419.html.下面,我能想出来的是,我自己在开发过程 ...

  7. oracle数据库中的存储过程

    存储过程是一组为了完成特定功能的sql语句集,是一段sql代码片段,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果存储过程存在参就给出,不存在就不用给出参数)来执行它.因为它是一段 ...

  8. 50. Pow(x, n) (JAVA)

    Implement pow(x, n), which calculates x raised to the power n(xn). Example 1: Input: 2.00000, 10 Out ...

  9. visual studio 2013 生成依赖项关系图出错

    开始是说无法连接到sql服务器,我安装卸载localdb http://www.microsoft.com/zh-cn/download/details.aspx?id=29062 下载 CHS\x6 ...

  10. JavaEE高级-SpringMVC学习笔记

    *SpringMVC概述 - Spring为展示层提供的基于MVC设计理念的优秀Web框架,是目前最主流的MVC框架之一 - Spring3.0后全面超越Struts2,成为最优秀的MVC框架 - S ...