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 }

 
时间: 2024-08-26 19:06:00

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

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

本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder机制,在网上查阅了大量的资料,也看了老罗的Binder系列的博客和Innost的深入理解Binder系列的博客,都是从底层开始讲的,全是C代码,虽然之前学过C和C++,然而各种函数之间花式跳转,看的我都怀疑人生.毫不夸张的讲每看一遍都是新的内容,跟没看过一样.后来又看到了Gityuan的博客看到了一

进程间通讯机制

1. 无名管道PIPE 作用:情缘关系进程间通信. 原理:是内核中一种特殊的临时文件,用完自动消失,数据采用循环队列的方式在进程间传递. 2. 有名管道FIFO 作用:任意进程间通信. 原理:是文件系统中特殊的永久文件,用完不会消失,但作用仅仅是拥有一个磁盘路径这样的接口,而通信的信息存只放在内存中. 3. 信号 4. 信号量 5. 消息队列 6. 共享内存 作用:实现进程间大量数据传输. 原理:在内存单独开辟一段内存空间,然后进程将这段内存空间挂载到该进程,通过信号量来使进程互斥的访问共享内存

实现类似于Qt的Signal和Slot通讯机制

Signal和Slot机制 其实qt提供的对象间通讯机制. 实现细节 思路 实现类似与信号与槽的机制,无非就是做一些薄记工作,qt中通过虚函数和moc来实现.那我们怎么实现?我的思路是signal是一个对象,其他的slot将自己的回调注册进signal对象中,signal完成薄记工作.那么需要实现的细节归于一下几点. 1. 参数的提取与匹配. 2. slot容器的制作. 3. slot的调用. 参数处理 怎么处理参数是一大难题.我们必须推导出各类型,包括类的类型和参数类型,在此我们引入很多特性模

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

ACE框架将基于共享内存的进程间通讯功能,如其它IO组件或IPC组件一样,设计成三个组件.流操作组件ACE_MEM_Stream,连接器组件ACE_MEM_Connector,以及接收连接组件ACE_MEM_Accpter.ACE框架为基于共享内存的进程间通讯提供了两种数据传输(分发deliver)策略.一种是使用生产者-消费者队列的一对多的多用户MT策略,另一种是使用socket流的可以使用反应器响应数据接收事件的Reactor策略.不论哪一种策略都要通过socket进行TCP连接,并进行进程

第23条:通过委托与数据源协议进行对象间通信

第4章:协议与分类 Objective-C 语言有一项特性叫做"协议"(protocol),它与 Jave 的 "接口"(interface)类似.Objective-C 不支持多重继承,因而我们把某个类应该实现的一系列方法定义在协议里面.协议最为常见的用途是实现委托模式,不过也有其他用法.理解并善用协议可令代码变得更易维护,因为协议这种方式能很好的描述接口. "分类"(category)也是 Objective-C 的一项重要语言特性.利用分类

C#进程间通讯技术-整理。

原文:C#进程间通讯技术-整理. 扩展阅读:http://www.cnblogs.com/joye-shen/archive/2012/06/16/2551864.html 一.进程间通讯的方式 1)共享内存 包括:内存映射文件,共享内存DLL,剪切板. 2)命名管道及匿名管道 3)消息通讯 4)利用代理方法.例如SOCKET,配置文件,注册表方式. 等方式. 方法一:通讯. 进程间通讯的方式有很多,常用的有共享内存(内存映射文件.共享内存DLL.剪切板等).命名管道和匿名管道.发送消息等几种方

Android AIDL 进行进程间通讯(IPC)

编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3.AIDL默认支持的类型包括java基本类型 (int.long.boolean等) 和 (String.List.Map.CharSequence),使用这些类型时不需要import声明.对于List和Map中的元素类型必须是AIDL支持的类型,如果使用自定义类型作为参数或者返回值,自定义类型必须实

线程间通信机制posix匿名信号量

信号量分为两种 一种是简单的信号量,另一种是用于进程间通信的信号量集. 简单的信号量 属于POSIX标准的信号量; 从信号量的命名来看,信号量又可分为命名信号量和匿名(未命名)信号量; 从信号量的值来看,信号量可分为二进制信号量和计数信号量; 1.匿名信号量和命名信号量: 匿名信号量是在内存中分配内存.进行初始化并由系统API进行管理的,它可以在多个线程之间进行资源同步,也可以在多个进程之间进行资源同步,这主要是看在初始化的时候给pshared传递的参数值,为0,则在线程之间同步,非0,则在进程

管道实现进程间通讯 、WaitNamedPipe

一.管道实现进程间通讯 主要的理论知识 1.什么是管道以及分类 管道是两个头的东西,每一个头各连接一个进程或者同一个进程的不同代码,依照管道的类别分有两种管道,匿名的和命名的:依照管道的传输方向分也能够分成两种,单向的双向的.依据管道的特点,命名管道通经常使用在网络环境下不同计算机上执行的进程之间的通信(当然也能够用在同一台机的不同进程中)它能够是单向或双向的:而匿名管道仅仅能用在同一台计算机中,它仅仅能是单向的.匿名管道事实上是通过用给了一个指定名字的有名管道来实现的. 使用管道的优点在于:读