实现一个高效C++委托类(多分派)
1、暂命名为Functor,因为没考虑返回值的情况,这在多分派委托处理中,算是个麻烦事,以后类名可能改为Delegate。
2、根据i_like_cpp翻译的技术文章《成员函数指针与高性能的C++委托》提供的思路做成的,不过原文所提到的FastDelegate实现太复杂,所以自己做了一个,可能不完善,不过初步测试基本功能达到了,而且实现要简单一些。
3、原本vector遍历用的是迭代器,不过测试发现速度比用下标访问慢10倍以上,改成下标访问,测试表明速度已经和直接调用差不多。实际测试结果非常相近,用GetTickCount获取的结果,有时是直接调用要快一些,有时是使用Functor要快一些,当然Functor不可能比直接调用还快。
4、实现没有写完,先写了3个版本做测试用,成型以后会实现更多版本(支持更多参数)。下午一时心血来潮写成的,离成型还很远,不过从效率测试来看值得做。
#include <functional>
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
struct Test
{
int n;
Test () : n(3) {}
void test0()
{
//cout << "Test::test0: " << n << endl;
}
void test1(int i)
{
//cout << "Test::test1: " << i << endl;
}
void test2(const string& a, int b)
{
//cout << "Test::test2: " << a << "|" << b << endl;
}
};
void test0 ()
{
//cout << "test0" << endl;
}
void test1 (int i)
{
//cout << "test1: " << i << endl;
}
void test2(const string& a, int b)
{
//cout << "test2: " << a << "|" << b << endl;
}
struct NullType {};
template <typename R, typename A=NullType, typename B=NullType, typename C=NullType,
typename D=NullType, typename E=NullType, typename F=NullType, typename G=NullType,
typename H=NullType, typename I=NullType, typename J=NullType, typename K=NullType,
typename L=NullType, typename M=NullType, typename N=NullType, typename O=NullType>
class Functor
{
};
template <typename R>
struct Functor <R>
{
vector <pair<void*, void*> > _handlers;
typedef R(*F)();
void add (F f)
{
_handlers.push_back (make_pair ((void*)0, (void*)f));
}
template <typename T>
void add (const pair<T*, typename R(T::*)()>& f)
{
typedef R(T::*P)();
struct Pointer {P p;};
Pointer ptr = {f.second};
_handlers.push_back (make_pair ((void*)f.first, *(void**)&ptr));
}
void call ()
{
for (size_t i=0; i<_handlers.size (); i++)
{
void* p = _handlers[i].first;
if (p) // member function
{
void* mem_fun = _handlers[i].second;
__asm{
mov ecx, p
call mem_fun
}
}
else
{
(*(F)_handlers[i].second)();
}
}
}
};
template <typename R, typename A>
struct Functor <R, A>
{
vector <pair<void*, void*> > _handlers;
typedef R(*F)(A);
void add (F f)
{
_handlers.push_back (make_pair ((void*)0, (void*)f));
}
template <typename T>
void add (const pair<T*, typename R(T::*)(A)>& f)
{
typedef R(T::*P)(A);
struct Pointer {P p;};
Pointer ptr = {f.second};
_handlers.push_back (make_pair ((void*)f.first, *(void**)&ptr));
}
void call (A a)
{
for (size_t i=0; i<_handlers.size (); i++)
{
void* p = _handlers[i].first;
if (p) // member function
{
void* mem_fun = _handlers[i].second;
__asm{
push a
mov ecx, p
call mem_fun
}
}
else
{
(*(F)_handlers[i].second)(a);
}
}
}
};
template <typename R, typename A, typename B>
struct Functor <R, A, B>
{
vector <pair<void*, void*> > _handlers;
typedef R(*F)(A, B);
void add (F f)
{
_handlers.push_back (make_pair ((void*)0, (void*)f));
}
template <typename T>
void add (const pair<T*, typename R(T::*)(A, B)>& f)
{
typedef R(T::*P)(A, B);
struct Pointer {P p;};
Pointer ptr = {f.second};
_handlers.push_back (make_pair ((void*)f.first, *(void**)&ptr));
}
void call (A a, B b)
{
for (size_t i=0; i<_handlers.size (); i++)
{
void* p = _handlers[i].first;
if (p) // member function
{
void* mem_fun = _handlers[i].second;
__asm{
push b
push a
mov ecx, p
call mem_fun
}
}
else
{
(*(F)_handlers[i].second)(a, b);
}
}
}
};
int main(int argc, char* argv[])
{
Test t;
DWORD cur = GetTickCount ();
for (int i=0; i<10000000; i++)
{
t.test0();
}
cout << (GetTickCount() - cur) << endl;
Functor <void> f;
f.add (make_pair(&t, &Test::test0));
f.add (test0);
cur = GetTickCount ();
for (int i=0; i<1000000; i++)
{
f.call();
}
cout << (GetTickCount() - cur) << endl;
f.call ();
Functor<void, int> f1;
f1.add (test1);
f1.add (make_pair (&t, &Test::test1));
f1.add (test1);
f1.add (test1);
f1.call (93);
Functor<void, const string&, int> f2;
f2.add (test2);
f2.add (make_pair (&t, &Test::test2));
f2.add (test2);
f2.add (test2);
f2.call (string("hello"), 5);
return 0;
}
转载于:https://www.cnblogs.com/cpunion/archive/2005/07/22/198288.html
实现一个高效C++委托类(多分派)相关推荐
- Java趣谈——如何构建一个高效且可伸缩的缓存
Java趣谈--如何构建一个高效且可伸缩的缓存 本集概要: 怎样构建一个线程安全而又高效.可伸缩的缓存? 怎样利用设计模式,把缓存做成通用的工具? 除了synchronize和volatile,我们还 ...
- 百度提出PADDLESEG:一个高效的图像分割开发工具
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 小白导读 论文是学术研究的精华和未来发展的明灯.小白决心每天为大家 ...
- 一个高效的定时任务系统
"今天想跟大家一起探讨一个听起来很简单的话题:定时任务机制. 无非就是一个计时器,到了指定时间就开始跑呗.too young,要是这么简单我还说啥呢,干不就完了. 那如果是几千上万个定时任务 ...
- 自己构建一个高效缓存服务!
点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:分享一个牛逼的 Java 开源后台管理系统,不要造轮子了!个人原创+1博客:点击前往,查看更多 作者:flyde ...
- 如何写一个高效进程/线程池_关于高效企业测试的思考(1/6)
如何写一个高效进程/线程池 企业中的测试仍然没有得到应有的广泛应用. 编写尤其是维护测试需要花费时间和精力,但是缩短软件测试并不是解决方案. 为了提高测试效率,应该追求哪些范围,方法和测试技术? 基于 ...
- python画画bup_Python中的高效Vector / Point类
实现高效的Vector / Point类的最佳方法是什么(甚至更好:是否有一个),可以在 Python 2.7和3.x中使用? 我找到了the blender-mathutils,但它们似乎只支持Py ...
- failed to open log file_C++中glog源码剖析以及如何设计一个高效 log模块
每个开发者编程中都会记录log信息,多数人都会使用log第三方库,log库使用起来很方便,但我们也需要了解log系统的原理,这里以glog为例进行分析. 开始 这里不会介绍glog中是如何控制INFO ...
- 线程安全list_多线程开发之如何创建一个线程安全的类
上一篇讨论了如何解决线程安全的问题,今天总结如何设计一个线程安全的类: 创建线程安全类的关注点 一个类要想线程安全,除了上一篇文章通过外部解决方式外,还可以通过合理的设计类的内部来解决,使类本身就线程 ...
- 优雅地实现一个高效、异步数据实时刷新的列表
今日科技快讯 2月11日消息,据CNBC报道,当特斯拉公司于2019年1月宣布第二轮裁员以控制成本时,一个关键部门受到的打击尤为沉重.两名被裁汰的员工表示,负责向北美地区客户交付Model 3电动汽车 ...
最新文章
- bootstrap的日期选择器 完整源码demo附效果图
- 文本挖掘预处理之向量化与Hash Trick
- 【Java核心计算 基础知识(第9版)】第3章 Java的基本程序设计结构
- 简单API接口签名验证
- Opengl超级宝典笔记——空间绘图画点
- [蓝桥杯][算法提高VIP]最小乘积(提高型)-排序
- zzulioj1111: 多个整数的逆序输出(函数专题)
- 【软件架构】三层架构和MVC的比较
- PCI、PCI-X、PCI-E AGP区别
- 启明星系统简介--兼论启明星OA思想
- 广州市车联网先导区建设总体技术规范
- 8 - 博客文章详情页
- 【Web安全笔记】之【9.0 工具与资源】
- 关于java一些星号三角形的实现
- IBDP tok课程是什么课?怎么拿高分?
- 著名数学家龚升的论述揭示高中“函数近代严格定义” 有非常明显错误
- 《程序员升职记》2.繁忙的收发室
- Uboot9之uboot目录分析
- java字母数字互相转换
- TCP多人聊天室实现 JSON文件解析
热门文章
- vue 如何处理两个组件异步问题_Vue异步组件处理路由组件加载状态的解决方案...
- 用一句话阐明epoll跟Windows IOCP之间的区别
- 安卓7.0海信定制版新增功能
- [整理] TPM 2.0 设备串口通讯协议中文文档
- 地图整饰-框架与格网
- 走在网页游戏开发的路上——页游资源管理
- matlab线性代数命令大全,线性代数 - MATLAB 系统中文帮助手册
- python 柱状图上显示字体_Python爬取百部电影数据,我发现了这个惊人真相!
- hive 中String对长度没有限制
- 熊海博客php版本,xhcms_v1.0 熊海CMS是由熊海开发的一款可广泛应用于个人博客 联合开发网 - pudn.com...