// 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++ 对象间通讯机制 框架实现的更多相关文章

  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. face-api.js 前端人脸识别,人脸检测,登录认证

    1.参考face-api.js https://github.com/justadudewhohacks/face-api.js#face-api.js-for-the-browser

  2. shell脚本每隔几秒执行

    while true do cmd(shell 命令) sleep x(x为秒数) done ————————————————版权声明:本文为CSDN博主「这年头起名真难3232」的原创文章,遵循 C ...

  3. [Web 前端] 029 jQuery 元素的“节操”

    目录 jQuery 元素的节点操作 1. 创建节点 2. 插入节点 2.1 在现存元素的内部,从后面插入元素 2.2 在现存元素的内部,从前面插入元素 2.3 在现存元素的外部,从后面插入元素 2.4 ...

  4. roslyn\csc.exe

    vs2019调试运行时提示roslyn\csc.exe错误时在nuget包管理器控制台里输入:  Update-Package Microsoft.CodeDom.Providers.DotNetCo ...

  5. 最大连续和 Medium

    Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous s ...

  6. 简述COOKIE和SESSION的区别与联系?

    cookie 和session 的区别:1.cookie数据存放在客户的浏览器上,session数据放在服务器上.2.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 ...

  7. Self-Driving Database

    最近一直在做 ML in Database 相关的工作.偶然发现CMU 19spring的15-721课程竟然专门安排了这个专题,不禁欣喜若狂,赶紧去学习了一下. Andy提出了self-drivin ...

  8. Quartz.NET | 佳佳的博客

    原文:Quartz.NET | 佳佳的博客 Quartz.NET 是一个定时计划任务的框架,支持 .NET Core. 本文示例代码大部分来自于官方教程:Quartz.NET - Quartz.NET ...

  9. Gradle Settings 类的学习

    # 任务 了解 Settings 类作用于 Gradle 构建的哪个阶段? 了解 Settings 类与 settings.gradle 的关系 了解和使用 inlcude 方法 hook 初始化阶段 ...

  10. 基于Nginx+nginx-rtmp-module+ffmpeg搭建rtmp、hls流媒体服务器

    上篇文章是基于Red5与ffmpeg实现rtmp处理NVR或摄像头的监控视频处理方案,有兴趣的朋友可以查看. Nginx及nginx-rtmp-module安装 新建目录 mkdir /usr/loc ...