zoukankan      html  css  js  c++  java
  • C++ 对象间通讯机制 框架实现

      1 // SignalSlot.h: interface for the CSignalSlot class.
      2 //
      3 //////////////////////////////////////////////////////////////////////
      4 
      5 #if !defined(AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_)
      6 #define AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_
      7 
      8 #include <Afxtempl.h>
      9 
     10 #if _MSC_VER > 1000
     11 #pragma once
     12 #endif // _MSC_VER > 1000
     13 
     14 // 15 // 16 
     17 //--------------------------------------------------------------------------------------------
     18 // 静态slot接口函数类型指针定义
     19 typedef int (__cdecl *SS_STAIC_SLOTFUNC)(void *pSelf,int slot_F,void *pSrc,void *pDes);
     20 
     21 // 数据结构定义
     22 struct FuncItem 
     23 {
     24     bool is_use;  //是否使用
     25     int signal_F;
     26     int slot_F;
     27 };
     28 
     29 struct SSItem
     30 {
     31     bool is_use;  //是否使用
     32 
     33     void* signal_pSelf;
     34     void* slot_pSelf;
     35 
     36     void* slot_pFunc;
     37     CArray<FuncItem,FuncItem>*pFuncArray;
     38 };
     39 
     40 //----------------------------------------------------------------------------------------------------------------------
     41 /* 
     42 宏定义1: 信号槽类注册
     43 说明: 信号槽(接收方)类定义需要使用该宏声明
     44 在类定义最开始位置声明,结尾不需要冒号。例子如下所示:
     45 class CTest
     46 {
     47     SS_REGISTER(CTest)
     48 public:
     49     ...
     50 }
     51 
     52 参数: ClassName 为类名称
     53 宏展开: 定义了一个公有静态函数:
     54         SS_STATIC_SLOT: 函数名称 
     55         pSelf: 类对象指针
     56         slot_F: 槽函数ID (成员函数指针转换得到)
     57         pSrc: 信号发送方输入参数void通用指针
     58         pDes: 返回参数内存指针(由调用方提供)
     59 */
     60 #define SS_REGISTER(ClassName) 
     61 public: static int _SS_STATIC_SLOT_(void *pSelf,int slot_F,void *pSrc,void *pDes)
     62 {
     63     typedef    int(ClassName::*SLOTFUNC)(void*pSrc,void*pDes=NULL);
     64     SLOTFUNC  slot_Func;
     65     int TEMP = (int)(&slot_Func);
     66     *((int*)(TEMP)) = slot_F;
     67     int res = (((ClassName*)(pSelf))->*slot_Func)(pSrc,pDes);
     68     return res;
     69 }
     70 
     71 // 宏定义2: 信号函数定义
     72 #define SS_SIGNAL(ClassName,FuncName) 
     73 int FuncName(void*pSrc,void*pDes=NULL)
     74 {
     75     typedef int(ClassName::*SLOTFUNC)(void*,void*);
     76     SLOTFUNC pfunc = &ClassName::FuncName;
     77     int funcID = *((int*)((int)(&pfunc)));
     78     return CSignalSlot::SignalSS(this,funcID,pSrc,pDes);
     79 }
     80 
     81 // 宏定义3: 初始化连接
     82 #define SS_INITE(signalSelf,slotSelf,res) 
     83 *res = CSignalSlot::IniteSS(signalSelf,slotSelf,(slotSelf)->_SS_STATIC_SLOT_);
     84 
     85 // 宏定义4: 解除对象连接
     86 #define SS_CLOSE(signalSelf,slotSelf,res) 
     87 *res = CSignalSlot::CloseSS(signalSelf,slotSelf);
     88 
     89 // 宏定义5: 连接功能函数
     90 #define SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) 
     91 {
     92   typedef int(signalClassName::*SIGNAL_PF)(void*,void*);
     93   typedef int(slotClassName::*SLOT_PF)(void*,void*);
     94   SIGNAL_PF Signal_F = &signalClassName::signalFunc;
     95   SLOT_PF slot_F = &slotClassName::slotFunc;
     96   *res = CSignalSlot::ConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F))));
     97 }
     98 
     99 // 宏定义6: 断开功能连接
    100 #define SS_DISCONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) 
    101 {
    102     typedef int(signalClassName::*SIGNAL_PF)(void*,void*);
    103     typedef int(slotClassName::*SLOT_PF)(void*,void*);
    104     SIGNAL_PF Signal_F = &signalClassName::signalFunc;
    105     SLOT_PF slot_F = &slotClassName::slotFunc;
    106     *res = CSignalSlot::DisConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F))));
    107 }
    108 
    109 // 宏定义7: 初始化连接(3与5的功能组合)   
    110 #define SS_INICONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) 
    111 SS_INITE(signalSelf,slotSelf,res)
    112 if(*res!=-1)
    113 SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res);
    114 //------------------------------------------------------------------------------------------------------------------------------
    115 
    116 class CSignalSlot
    117 {
    118 public: 
    119     static int DisConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F);
    120     static int CloseSS(void *signal_pSelf,void*slot_pSelf);
    121     static int IniteSS(void* signal_pSelf,void* slot_pSelf,SS_STAIC_SLOTFUNC slot_pFunc);
    122     static int SignalSS(void *signal_pSelf,int signal_F,void *pSrc,void *pDes=NULL);
    123     static int ConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F);
    124     CSignalSlot();
    125     virtual ~CSignalSlot();
    126 private:
    127     static void CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray);
    128     static CArray<SSItem,SSItem>m_SSArray;
    129     static int m_loopback;
    130 };
    131 
    132 #endif // !defined(AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_)

      1 // SignalSlot.cpp: implementation of the CSignalSlot class.
      2 //
      3 //////////////////////////////////////////////////////////////////////
      4 
      5 #include "stdafx.h"
      6 #include "SignalSlot.h"
      7 
      8 #ifdef _DEBUG
      9 #undef THIS_FILE
     10 static char THIS_FILE[]=__FILE__;
     11 #define new DEBUG_NEW
     12 #endif
     13 
     14 //////////////////////////////////////////////////////////////////////
     15 // Construction/Destruction
     16 //////////////////////////////////////////////////////////////////////
     17 CArray<SSItem,SSItem> CSignalSlot::m_SSArray;
     18 int CSignalSlot::m_loopback = 0;
     19 
     20 CSignalSlot::CSignalSlot()
     21 {
     22     
     23 }
     24 
     25 CSignalSlot::~CSignalSlot()
     26 {
     27 
     28 }
     29 
     30 //初始化对象连接  建立非对称连接  signal对象可以往slot对象发消息   一条单向通信链路定义为一个连接项
     31 // 返回值:1  成功    0 已存在该连接     -1 添加失败
     32 int CSignalSlot::IniteSS(void* signal_pSelf,void* slot_pSelf,SS_STAIC_SLOTFUNC slot_pFunc)
     33 {
     34     int len = CSignalSlot::m_SSArray.GetSize();
     35     SSItem tItem;
     36     int nPos = -1;
     37     // 扫描是否已存在该连接(同时记录下第一个位置内存项记录)
     38     for(int i=0;i<len;i++)
     39     {
     40         tItem = CSignalSlot::m_SSArray.GetAt(i);
     41         if(true==tItem.is_use)
     42         {
     43             if(signal_pSelf==tItem.signal_pSelf && slot_pSelf==tItem.slot_pSelf)
     44             {
     45                 return 0; // 已存在该连接
     46             }
     47         }
     48         else
     49         {
     50             if(-1==nPos)
     51             {
     52                 nPos = i;// 记住第一个扫描到的位置用内存项位置
     53             }
     54         }
     55     }
     56     
     57     //增加新连接
     58     if(nPos!=-1)// 占用空闲位置项
     59     {
     60         tItem = CSignalSlot::m_SSArray.GetAt(nPos);
     61         tItem.is_use = TRUE;
     62         tItem.signal_pSelf = signal_pSelf;
     63         tItem.slot_pSelf = slot_pSelf;
     64         tItem.slot_pFunc = slot_pFunc;
     65 
     66         CSignalSlot::m_SSArray.SetAt(nPos,tItem);
     67         return 1;
     68     }else //新增位置项
     69     {
     70         tItem.is_use = TRUE;
     71         tItem.signal_pSelf = signal_pSelf;
     72         tItem.slot_pSelf = slot_pSelf;
     73         tItem.slot_pFunc = slot_pFunc;
     74         tItem.pFuncArray = new CArray<FuncItem,FuncItem>;
     75         CSignalSlot::m_SSArray.Add(tItem);
     76         return 1;
     77     }
     78 }
     79 
     80 // 信号|槽连接: <signal对象+成员函数ID,slot对象+成员函数>作为一个连接项
     81 // 返回值:1:成功    0:已存在该连接项     -1:添加失败
     82 int CSignalSlot::ConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F)
     83 {
     84     int len = CSignalSlot::m_SSArray.GetSize();
     85     SSItem sItem;
     86     FuncItem fItem;
     87     int nPos = -1;
     88     for (int i=0;i<len;i++)
     89     {
     90         sItem = CSignalSlot::m_SSArray.GetAt(i);
     91         if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf && true==sItem.is_use)
     92         {
     93             int sum = sItem.pFuncArray->GetSize();
     94             for(int k=0;k<sum;k++)
     95             {
     96                 fItem= sItem.pFuncArray->GetAt(k);
     97                 if(true==fItem.is_use)
     98                 {
     99                     if(signal_F==fItem.signal_F && slot_F==fItem.slot_F)
    100                     {
    101                         return 0;  //已存在该连接
    102                     }
    103                 }else
    104                 {
    105                     if(-1==nPos)
    106                     {
    107                         nPos = k;
    108                     }
    109                 }
    110             }
    111             // 新增连接
    112             fItem.is_use = true;
    113             fItem.signal_F = signal_F;
    114             fItem.slot_F = slot_F;
    115             if(nPos!=-1)
    116             {
    117                 sItem.pFuncArray->SetAt(nPos,fItem);
    118                 return 1;
    119             }else
    120             {
    121                 sItem.pFuncArray->Add(fItem);
    122                 return 1;
    123             }
    124         }
    125     }
    126 
    127     return -1;   // 对象连接没有初始化
    128 }
    129 
    130 // 返回值: 调用槽的执行数目(每调用一个槽函数,返回值加1)
    131 int CSignalSlot::SignalSS(void *signal_pSelf,int signal_F,void *pSrc, void *pDes)
    132 {
    133     int res = 0;
    134     int len  = CSignalSlot::m_SSArray.GetSize();
    135     for(int i=0;i<len;i++)
    136     {
    137         SSItem ssitem = CSignalSlot::m_SSArray.GetAt(i);
    138         if(ssitem.is_use == true && signal_pSelf==ssitem.signal_pSelf) //找到对象连接
    139         {
    140             int sum = ssitem.pFuncArray->GetSize();
    141             for(int k=0;k<sum;k++)
    142             {
    143                 FuncItem fitem = ssitem.pFuncArray->GetAt(k);
    144                 if(fitem.is_use==true && signal_F==fitem.signal_F)  //找到信号|槽连接
    145                 {
    146                     ////////////////////////////////////////////////////////////////////////////
    147                     if(CSignalSlot::m_loopback>0)    //判断是否出现回环(避免信号函数的嵌套调用)
    148                     {
    149                         CSignalSlot::m_loopback = 0; //清除嵌套计数    
    150                         return 0;  // 中断返回
    151                     }
    152                     CSignalSlot::m_loopback += 1;
    153                     /////////////////////////////////////////////////////////////////////////////
    154 
    155                     SS_STAIC_SLOTFUNC tempFunc = (SS_STAIC_SLOTFUNC)ssitem.slot_pFunc;
    156                     tempFunc(ssitem.slot_pSelf,fitem.slot_F,pSrc,pDes); //通过静态槽接口函数发起调用
    157                     res+=1;
    158                 }
    159             }
    160         }
    161     }
    162 
    163     CSignalSlot::m_loopback=0; //清除嵌套计数
    164     return res;
    165 }
    166 
    167 // 关闭删除对象连接(单向)
    168 // 返回值:>0 成功    0 已不存在该连接     -1 删除失败
    169 int CSignalSlot::CloseSS(void *signal_pSelf, void *slot_pSelf)
    170 {
    171     int len = CSignalSlot::m_SSArray.GetSize();
    172     SSItem sItem;
    173     int res = 0;
    174     for(int i=0;i<len;i++)
    175     {
    176         sItem = CSignalSlot::m_SSArray.GetAt(i);
    177         if(false==sItem.is_use)
    178         {
    179             continue;
    180         }
    181         if(NULL==signal_pSelf)
    182         {
    183             if(slot_pSelf==sItem.slot_pSelf)
    184             {
    185                 sItem.is_use = false;
    186                 CSignalSlot::CloseFuncArray(sItem.pFuncArray);
    187                 res+=1;
    188             }
    189         }else if(NULL==slot_pSelf)
    190         {
    191             if(signal_pSelf==sItem.signal_pSelf)
    192             {
    193                 sItem.is_use = false;
    194                 CSignalSlot::CloseFuncArray(sItem.pFuncArray);
    195                 res+=1;
    196             }
    197         }else if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf)
    198         {
    199             sItem.is_use = false;
    200             CSignalSlot::CloseFuncArray(sItem.pFuncArray);
    201             res+=1;
    202             break;
    203         }
    204     }
    205     return res;
    206 }
    207 
    208 
    209 // 删除信号槽连接
    210 // 返回值:1 成功    0 已不存在该连接   -1 删除失败
    211 int CSignalSlot::DisConnectSS(void *signal_pSelf, int signal_F, void *slot_pSelf, int slot_F)
    212 {
    213     int len = CSignalSlot::m_SSArray.GetSize();
    214     SSItem sItem;
    215     for (int i=0;i<len;i++)
    216     {
    217         sItem = CSignalSlot::m_SSArray.GetAt(i);
    218         if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf &&true==sItem.is_use)
    219         {
    220             int sum = sItem.pFuncArray->GetSize();
    221             FuncItem item;
    222             for(int k=0;k<sum;k++)
    223             {
    224                 item = sItem.pFuncArray->GetAt(k);
    225                 if(signal_F==item.signal_F && slot_F==item.slot_F)
    226                 {
    227                     item = sItem.pFuncArray->GetAt(k);
    228                     item.is_use = false;
    229                     sItem.pFuncArray->SetAt(k,item);
    230                     return 1;  //删除连接
    231                 }
    232             }
    233         }
    234     }
    235 
    236     return 0;   // 对象连接没有初始化
    237 }
    238 
    239 
    240 void CSignalSlot::CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray)
    241 {
    242      int sum = pFuncArray->GetSize();
    243      FuncItem item;
    244      for(int k=0;k<sum;k++)
    245      {
    246          item = pFuncArray->GetAt(k);
    247          item.is_use = false;
    248          pFuncArray->SetAt(k,item);
    249      }
    250 }
    
    
    
     
  • 相关阅读:
    Linux——shell简单学习(一)
    Linux——进程管理简单学习笔记(二)
    Linux——进程管理学习简单笔记
    Linux——用户管理简单学习笔记(四)
    PHP计算程序运行时间的类
    php几个常用的概率算法(抽奖、广告首选)
    限制非安全IP访问
    简单的点击短信发送计时器
    php 以图搜图
    递归获取二维数组后代、删除后代
  • 原文地址:https://www.cnblogs.com/Esperanto/p/5179505.html
Copyright © 2011-2022 走看看