// 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. Service-Oriented Architecture,SOA(转)

    http://blog.csdn.net/WOOSHN/article/details/8036910 介绍: IT体系结构已非常成熟,它是一种成功处理典型IT问题的方法.体系结构中一个受到很大重视且 ...

  2. C语言中,当计算字符数组长度时,用sizeof 和strlen 的原理及两者的区别

    字符数组的长度计算:必须以终止符’\0'作为边界,但对字符数组赋值时,有两种方式: 1:定义时用字符初始化 (1)char chs[7] = {'a', 'c', '0', 'z', '3','d'} ...

  3. Scala学习笔记(6)对象

    1.单例对象.Scala没有静态方法或字段,可以使用object这个语法结构来达到同样的目的.对象定义了单个实例,包含了你想要的特性. object Accounts{ def newUniqueNu ...

  4. htm、html、shtml区别。(web服务器配置ssi)

    转载源:http://www.divcss5.com/html/h59.shtml 首先htm.html.shtml都是静态网页的后缀,三者也可以说都是只是扩展名不同,其他一样,都是静态的网页.Htm ...

  5. python利用(threading,ThreadPoolExecutor.map,ThreadPoolExecutor.submit) 三种多线程方式处理 list数据

    需求:在从银行数据库中取出 几十万数据时,需要对 每行数据进行相关操作,通过pandas的dataframe发现数据处理过慢,于是 对数据进行 分段后 通过 线程进行处理: 如下给出 测试版代码,通过 ...

  6. Mysql 服务器管理程序 mysqladmin

    mysqladmin [oprions] command 选项                                      说明 create db_name               ...

  7. 3.17内存,进程,rpm和yum,python编译安装

    一.内存 前面说过内存有寄存器.高速缓存和内存条 但在实际情况中有些文件比较大,内存不足以读取其内容,并且大部分内容不是被立即使用,所以有了交换分区,即用硬盘空间临时存储相关部分,当作缓存,这部分就是 ...

  8. PC端网站微信扫码登录

    需求分析:用户通过扫描我们网页的二维码,如果已经绑定我们平台的账户,即成功进入首页,否则提示先绑定个人微信账号. 1.绑定微信账号:是通过关注微信公众号实现绑定个人微信账号.首先通过后台接口获取到ti ...

  9. 005-sort 命令使用

    字符处理命令 sort 排序命令 排序选项: -f, --ignore-case 忽略字母大小写 -n, --numeric-sort 根据字符串数值比较 -r, --reverse 逆序输出排序结果 ...

  10. 洛谷 P2866 [USACO06NOV]糟糕的一天Bad Hair Day 牛客假日团队赛5 A (单调栈)

    链接:https://ac.nowcoder.com/acm/contest/984/A 来源:牛客网 题目描述 Some of Farmer John's N cows (1 ≤ N ≤ 80,00 ...