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的 ...
随机推荐
- xmake从入门到精通10:多个子工程目标的依赖配置
xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验. 本文主要详细讲解下,如果在一个项目中维护和生成多个 ...
- k8s--资源控制器
资源控制器 1.什么是控制器 Kubernetes中内建了很多controller (控制器) ,这些相当于一个状态机,用来控制Pod的具体状态和行为 Pod 的分类 自主式 Pod:Pod 退出了, ...
- [转帖]功耗降50%,性能升35%!三星3nm GAA 2021年量产
功耗降50%,性能升35%!三星3nm GAA 2021年量产 http://www.chinaflashmarket.com/Instructor 在三星晶圆代工技术论坛(Samsung Found ...
- exists、in和join比较
这个根据实际情况具体分析 遇到问题了再具体分析就行.
- net 架构师-数据库-sql server-002-工具
本章讲述的工具包括: SQL Server 联机丛书 SQL Server配置管理器 SQL Server Management Studio SQL Server Business Intellig ...
- Windows 运行时加载动态库
下面是一个运行时加载nvcuda.dll,并检测当前驱动版本最大支持的CUDA版本的例子. #include "cuda.h" #include <stdio.h> # ...
- 题解 CF1119A 【Ilya and a Colorful Walk】
此题就是:给你一个数组,让你找出两个不同的元素,并让它们的下标差距最大. 思路:从2到n,如果与1不同,记录距离,与原数比较,取大. 从1到n-1,如果与n不同,记录距离,与原数比较,取大. AC代码 ...
- 打印Java main参数
public class Main { public static void main(String args[]){ System.out.println("打印main方法中的输入参数, ...
- PCIeの数据链路层与物理层详解
数据链路层(DLL,Data Link Layer)的主要作用是进行链路管理(Link Management).TLP错误校验.Flow Control(流控制)和Link功耗管理.不仅可以接收发送来 ...
- C/C++ 内存与指针
内存与指针杂谈 1.指针 1.数组指针 int(*ptr)[n] ()的优先级高,(*ptr)表示ptr是一个指针,指向一个int类型的一维数组,这个数组的长度为n,也可以说ptr的步长就是n.也就是 ...