C++ 对象间通讯机制 框架实现
// SignalSlot.h: interface for the CSignalSlot class.
//
////////////////////////////////////////////////////////////////////// #if !defined(AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_)
#define AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_ #include <Afxtempl.h> #if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000 // //
//--------------------------------------------------------------------------------------------
// 静态slot接口函数类型指针定义
typedef int (__cdecl *SS_STAIC_SLOTFUNC)(void *pSelf,int slot_F,void *pSrc,void *pDes); // 数据结构定义
struct FuncItem
{
bool is_use; //是否使用
int signal_F;
int slot_F;
}; struct SSItem
{
bool is_use; //是否使用 void* signal_pSelf;
void* slot_pSelf; void* slot_pFunc;
CArray<FuncItem,FuncItem>*pFuncArray;
}; //----------------------------------------------------------------------------------------------------------------------
/*
宏定义1: 信号槽类注册
说明: 信号槽(接收方)类定义需要使用该宏声明
在类定义最开始位置声明,结尾不需要冒号。例子如下所示:
class CTest
{
SS_REGISTER(CTest)
public:
...
} 参数: ClassName 为类名称
宏展开: 定义了一个公有静态函数:
SS_STATIC_SLOT: 函数名称
pSelf: 类对象指针
slot_F: 槽函数ID (成员函数指针转换得到)
pSrc: 信号发送方输入参数void通用指针
pDes: 返回参数内存指针(由调用方提供)
*/
#define SS_REGISTER(ClassName) \
public: static int _SS_STATIC_SLOT_(void *pSelf,int slot_F,void *pSrc,void *pDes)\
{\
typedef int(ClassName::*SLOTFUNC)(void*pSrc,void*pDes=NULL);\
SLOTFUNC slot_Func;\
int TEMP = (int)(&slot_Func);\
*((int*)(TEMP)) = slot_F;\
int res = (((ClassName*)(pSelf))->*slot_Func)(pSrc,pDes);\
return res;\
} // 宏定义2: 信号函数定义
#define SS_SIGNAL(ClassName,FuncName) \
int FuncName(void*pSrc,void*pDes=NULL)\
{\
typedef int(ClassName::*SLOTFUNC)(void*,void*);\
SLOTFUNC pfunc = &ClassName::FuncName;\
int funcID = *((int*)((int)(&pfunc)));\
return CSignalSlot::SignalSS(this,funcID,pSrc,pDes);\
} // 宏定义3: 初始化连接
#define SS_INITE(signalSelf,slotSelf,res) \
*res = CSignalSlot::IniteSS(signalSelf,slotSelf,(slotSelf)->_SS_STATIC_SLOT_); // 宏定义4: 解除对象连接
#define SS_CLOSE(signalSelf,slotSelf,res) \
*res = CSignalSlot::CloseSS(signalSelf,slotSelf); // 宏定义5: 连接功能函数
#define SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) \
{\
typedef int(signalClassName::*SIGNAL_PF)(void*,void*);\
typedef int(slotClassName::*SLOT_PF)(void*,void*);\
SIGNAL_PF Signal_F = &signalClassName::signalFunc;\
SLOT_PF slot_F = &slotClassName::slotFunc;\
*res = CSignalSlot::ConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F))));\
} // 宏定义6: 断开功能连接
#define SS_DISCONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) \
{\
typedef int(signalClassName::*SIGNAL_PF)(void*,void*);\
typedef int(slotClassName::*SLOT_PF)(void*,void*);\
SIGNAL_PF Signal_F = &signalClassName::signalFunc;\
SLOT_PF slot_F = &slotClassName::slotFunc;\
*res = CSignalSlot::DisConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F))));\
} // 宏定义7: 初始化连接(3与5的功能组合)
#define SS_INICONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) \
SS_INITE(signalSelf,slotSelf,res)\
if(*res!=-)\
SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res);
//------------------------------------------------------------------------------------------------------------------------------ class CSignalSlot
{
public:
static int DisConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F);
static int CloseSS(void *signal_pSelf,void*slot_pSelf);
static int IniteSS(void* signal_pSelf,void* slot_pSelf,SS_STAIC_SLOTFUNC slot_pFunc);
static int SignalSS(void *signal_pSelf,int signal_F,void *pSrc,void *pDes=NULL);
static int ConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F);
CSignalSlot();
virtual ~CSignalSlot();
private:
static void CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray);
static CArray<SSItem,SSItem>m_SSArray;
static int m_loopback;
}; #endif // !defined(AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_)
// SignalSlot.cpp: implementation of the CSignalSlot class.
//
////////////////////////////////////////////////////////////////////// #include "stdafx.h"
#include "SignalSlot.h" #ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif //////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CArray<SSItem,SSItem> CSignalSlot::m_SSArray;
int CSignalSlot::m_loopback = ; CSignalSlot::CSignalSlot()
{ } CSignalSlot::~CSignalSlot()
{ } //初始化对象连接 建立非对称连接 signal对象可以往slot对象发消息 一条单向通信链路定义为一个连接项
// 返回值:1 成功 0 已存在该连接 -1 添加失败
int CSignalSlot::IniteSS(void* signal_pSelf,void* slot_pSelf,SS_STAIC_SLOTFUNC slot_pFunc)
{
int len = CSignalSlot::m_SSArray.GetSize();
SSItem tItem;
int nPos = -;
// 扫描是否已存在该连接(同时记录下第一个位置内存项记录)
for(int i=;i<len;i++)
{
tItem = CSignalSlot::m_SSArray.GetAt(i);
if(true==tItem.is_use)
{
if(signal_pSelf==tItem.signal_pSelf && slot_pSelf==tItem.slot_pSelf)
{
return ; // 已存在该连接
}
}
else
{
if(-==nPos)
{
nPos = i;// 记住第一个扫描到的位置用内存项位置
}
}
} //增加新连接
if(nPos!=-)// 占用空闲位置项
{
tItem = CSignalSlot::m_SSArray.GetAt(nPos);
tItem.is_use = TRUE;
tItem.signal_pSelf = signal_pSelf;
tItem.slot_pSelf = slot_pSelf;
tItem.slot_pFunc = slot_pFunc; CSignalSlot::m_SSArray.SetAt(nPos,tItem);
return ;
}else //新增位置项
{
tItem.is_use = TRUE;
tItem.signal_pSelf = signal_pSelf;
tItem.slot_pSelf = slot_pSelf;
tItem.slot_pFunc = slot_pFunc;
tItem.pFuncArray = new CArray<FuncItem,FuncItem>;
CSignalSlot::m_SSArray.Add(tItem);
return ;
}
} // 信号|槽连接: <signal对象+成员函数ID,slot对象+成员函数>作为一个连接项
// 返回值:1:成功 0:已存在该连接项 -1:添加失败
int CSignalSlot::ConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F)
{
int len = CSignalSlot::m_SSArray.GetSize();
SSItem sItem;
FuncItem fItem;
int nPos = -;
for (int i=;i<len;i++)
{
sItem = CSignalSlot::m_SSArray.GetAt(i);
if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf && true==sItem.is_use)
{
int sum = sItem.pFuncArray->GetSize();
for(int k=;k<sum;k++)
{
fItem= sItem.pFuncArray->GetAt(k);
if(true==fItem.is_use)
{
if(signal_F==fItem.signal_F && slot_F==fItem.slot_F)
{
return ; //已存在该连接
}
}else
{
if(-==nPos)
{
nPos = k;
}
}
}
// 新增连接
fItem.is_use = true;
fItem.signal_F = signal_F;
fItem.slot_F = slot_F;
if(nPos!=-)
{
sItem.pFuncArray->SetAt(nPos,fItem);
return ;
}else
{
sItem.pFuncArray->Add(fItem);
return ;
}
}
} return -; // 对象连接没有初始化
} // 返回值: 调用槽的执行数目(每调用一个槽函数,返回值加1)
int CSignalSlot::SignalSS(void *signal_pSelf,int signal_F,void *pSrc, void *pDes)
{
int res = ;
int len = CSignalSlot::m_SSArray.GetSize();
for(int i=;i<len;i++)
{
SSItem ssitem = CSignalSlot::m_SSArray.GetAt(i);
if(ssitem.is_use == true && signal_pSelf==ssitem.signal_pSelf) //找到对象连接
{
int sum = ssitem.pFuncArray->GetSize();
for(int k=;k<sum;k++)
{
FuncItem fitem = ssitem.pFuncArray->GetAt(k);
if(fitem.is_use==true && signal_F==fitem.signal_F) //找到信号|槽连接
{
////////////////////////////////////////////////////////////////////////////
if(CSignalSlot::m_loopback>) //判断是否出现回环(避免信号函数的嵌套调用)
{
CSignalSlot::m_loopback = ; //清除嵌套计数
return ; // 中断返回
}
CSignalSlot::m_loopback += ;
///////////////////////////////////////////////////////////////////////////// SS_STAIC_SLOTFUNC tempFunc = (SS_STAIC_SLOTFUNC)ssitem.slot_pFunc;
tempFunc(ssitem.slot_pSelf,fitem.slot_F,pSrc,pDes); //通过静态槽接口函数发起调用
res+=;
}
}
}
} CSignalSlot::m_loopback=; //清除嵌套计数
return res;
} // 关闭删除对象连接(单向)
// 返回值:>0 成功 0 已不存在该连接 -1 删除失败
int CSignalSlot::CloseSS(void *signal_pSelf, void *slot_pSelf)
{
int len = CSignalSlot::m_SSArray.GetSize();
SSItem sItem;
int res = ;
for(int i=;i<len;i++)
{
sItem = CSignalSlot::m_SSArray.GetAt(i);
if(false==sItem.is_use)
{
continue;
}
if(NULL==signal_pSelf)
{
if(slot_pSelf==sItem.slot_pSelf)
{
sItem.is_use = false;
CSignalSlot::CloseFuncArray(sItem.pFuncArray);
res+=;
}
}else if(NULL==slot_pSelf)
{
if(signal_pSelf==sItem.signal_pSelf)
{
sItem.is_use = false;
CSignalSlot::CloseFuncArray(sItem.pFuncArray);
res+=;
}
}else if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf)
{
sItem.is_use = false;
CSignalSlot::CloseFuncArray(sItem.pFuncArray);
res+=;
break;
}
}
return res;
} // 删除信号槽连接
// 返回值:1 成功 0 已不存在该连接 -1 删除失败
int CSignalSlot::DisConnectSS(void *signal_pSelf, int signal_F, void *slot_pSelf, int slot_F)
{
int len = CSignalSlot::m_SSArray.GetSize();
SSItem sItem;
for (int i=;i<len;i++)
{
sItem = CSignalSlot::m_SSArray.GetAt(i);
if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf &&true==sItem.is_use)
{
int sum = sItem.pFuncArray->GetSize();
FuncItem item;
for(int k=;k<sum;k++)
{
item = sItem.pFuncArray->GetAt(k);
if(signal_F==item.signal_F && slot_F==item.slot_F)
{
item = sItem.pFuncArray->GetAt(k);
item.is_use = false;
sItem.pFuncArray->SetAt(k,item);
return ; //删除连接
}
}
}
} return ; // 对象连接没有初始化
} void CSignalSlot::CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray)
{
int sum = pFuncArray->GetSize();
FuncItem item;
for(int k=;k<sum;k++)
{
item = pFuncArray->GetAt(k);
item.is_use = false;
pFuncArray->SetAt(k,item);
}
}
C++ 对象间通讯机制 框架实现的更多相关文章
- 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制【转】
本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder ...
- Android Binder 进程间通讯机制梳理
什么是 Binder ? Binder是Android系统中进程间通讯(IPC)的一种方式,也是Android系统中最重要的特性之一.Binder的设计采用了面向对象的思想,在Binder通信模型的四 ...
- 如何才能学到Qt的精髓——信号槽之间的无关性,提供了绝佳的对象间通讯方式,QT的GUI全是自己的一套,并且完全开源,提供了一个绝好机会窥视gui具体实现
姚冬,中老年程序员 叶韵.KY Xu.赵奋强 等人赞同 被邀请了很久了,一直在思考,今天终于下决心开始写回答. 这个问题的确是够大的,Qt的代码规模在整个开源世界里也是名列前茅的,这么大的项目其中的精 ...
- C#进程间通讯或同步的框架引荐
这篇文章主要介绍了一个进程间通讯同步的C#框架,代码具有相当的稳定性和可维护性,随着.NET的开源也会被注入更多活力,推荐!需要的朋友可以参考下 0.背景简介 微软在 .NET 框架中提供了多种实用 ...
- java 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)
参考文章:http://ifeve.com/java-concurrency-thread-directory/ 其中的竞态,线程安全,内存模型,线程间的通信,java ThreadLocal类小节部 ...
- 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)
原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...
- 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 进程间 通讯 ...
- ACE框架 基于共享内存的进程间通讯
ACE框架将基于共享内存的进程间通讯功能,如其它IO组件或IPC组件一样,设计成三个组件.流操作组件ACE_MEM_Stream,连接器组件ACE_MEM_Connector,以及接收连接组件ACE_ ...
- Node.js - 阿里Egg的多进程模型和进程间通讯
前言 最近用Egg作为底层框架开发项目,好奇其多进程模型的管理实现,于是学习了解了一些东西,顺便记录下来.文章如有错误, 请轻喷 为什么需要多进程 伴随科技的发展, 现在的服务器基本上都是多核cpu的 ...
随机推荐
- 在线cron表达式生成工具
http://cron.qqe2.com/ 名称 是否必须 允许值 特殊字符 秒 是 0-59 , - * / 分 是 0-59 , - * / 时 是 0-23 , - * / 日 是 1-31 , ...
- python控制流-名词解释
一.控制流的元素 控制流语句的开始部分通常是“条件”,接下来是一个代码块,称为“子句”. 二.控制流的条件 条件为了判断下一步如何进行,从而求布尔值的表达式.几乎所有的控制流语句都使用条件. 三.代码 ...
- 第四周预习作业and第五周作业
第四周预习作业 统计一行文本的单词个数 本题目要求编写程序统计一行字符中单词的个数.所谓"单词"是指连续不含空格的字符串,各单词之间用空格分隔,空格数可以是多个. 输入格式: 输入 ...
- 2019 计蒜之道 初赛 第一场 商汤的AI伴游小精灵
https://nanti.jisuanke.com/t/39260 根据题意我们可以知道 这是一个树 我们只需要找到出度最大的两个点就好了 如果包含根节点的话要-- 两个点相邻的话也要-- 数据很 ...
- adb常用命令和抓取log的方法
一 adb常用的几个命令1. 查看设备adb devices这个命令是查看当前连接的设备, 连接到计算机的android设备或者模拟器将会列出显示 C:\Documents and Settings\ ...
- POJ 3410 Split convex polygon(凸包)
题意是逆时针方向给你两个多边形,问你这两个多边形通过旋转和平移能否拼成一个凸包. 首先可以想到的便是枚举边,肯定是有一对长度相同的边贴合,那么我们就可以n2枚举所有边对,接下来就是旋转点对,那么假设多 ...
- TScreen研究(有待研究)
先扔在这里,待研究: http://blog.csdn.net/lailai186/article/details/8141170 procedure TForm1.Button1Click(Send ...
- [51Nod1850] 抽卡大赛
link $solution:$ 朴素 $dp$,暴力枚举选择 $i$ 号人的第 $j$ 张卡片,朴素 $dp$ 即可,时间复杂度 $O(n^4)$ . 考虑对于朴素 $dp$ 的优化,发现其实是一个 ...
- go & Windows Service
相关库 https://godoc.org/golang.org/x/sys/windows/svc https://github.com/kardianos/service https://gith ...
- django部署到linux上不显示.svg图标处理方法
在setting文件的最开始添加如下内容: import mimetypes mimetypes.add_type("image/svg+xml", ".svg" ...