// 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. 【Linux开发】将cmd中命令输出保存为TXT文本文件

    将cmd中命令输出保存为TXT文本文件 在网上看到一篇名为:"[转载]如何将cmd中命令输出保存为TXT文本文件" 例如:将Ping命令的加长包输出到D盘的ping.txt文本文件 ...

  2. 深入理解java:1.1.1. 反射机制

    反射 到底什么是反射(Reflection)呢? 反射有时候也被称为内省(Introspection),事实上,反射,就是一种内省的方式, Java不允许在运行时改变程序结构或类型变量的结构,但它允许 ...

  3. HTTPS测试

    1.首先理解HTTPS的含义,清楚http与HTTPS的区别 2.相对于http而言,https更加安全,因 3.使用数字证书使传输更安全,数字证书使用keytool工具生成 测试准备: 创建公钥和秘 ...

  4. Miller-Robin 素数测试法 模板

    测试单个素数,出错概率比计算机本身出错的概率还要低 算法是基于费马小定理(format),二次探测定理(x*x % p == 1 ,若P为素数,则x的解只能是x = 1或者x = p - 1)加上迭代 ...

  5. 牛客练习赛46 E 华华和奕奕学物理 (树状数组)

    https://ac.nowcoder.com/acm/contest/894/E 一开始写了一个简单的模拟 通过率只有5%...... 看题解真的理解了好久!!肥宅大哭orz 题解如下 最后一句:“ ...

  6. 【监控笔记】【1.5】事件通知(event Notification)

    关键词:DDL监控 [监控笔记][1.5]事件通知(event Notification) 注意,只能通过删除新建来修改事件. [1]概念 事件通知是特殊类型的数据库对象,用于将有关服务器和数据库实践 ...

  7. SQL Server中的扩展事件学习系列

    SQL Server 扩展事件(Extented Events)从入门到进阶(1)——从SQL Trace到Extented Events SQL Server 扩展事件(Extented Event ...

  8. Python 入门之 文件

    Python 入门之 文件 1.文件操作 找到文件位置 双击打开 进行一些操作 r-read(读) w-write(写) a-追加 rd--读字节 wd--清空写,写字节 ad --追加写(字节) r ...

  9. 在Visual studio 2017中使用EF6连接MySQL

    在Visual studio 2017中使用EF6连接Mysql ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) ...

  10. netperf编译./configure时报错 "error: cannot guess build type;you nust specify one"

    问题: 解决办法-亲测可用: 尝试:./configure --build=mingw提示无法辨别 checking build system type... Invalid configuratio ...