试想一下, 有没有这种需求:

对于每一个新的对象, 我们希望它能够在一定时间后自动销毁, 前提是我们没有在这段时间内给它发出重置信号.

这种需求其实是有的, 比如在电影里, 主角知道了一个反派不希望被揭露的秘密, 同时需要保住自己的性命, 那么就可以构造这样一个对象, 如果24小时内主角不给这个对象发送重置的信号, 它就会将这个秘密公之于众. 再比如, 在网络应用场景里, 我们希望每一个客户端能够定时给我们发送心跳包, 如果长时间不发送的话, 我们就剔除这个客户.

在之前的文章里, 我尝试使用了WIN32的Timer, 但是发现这种做法非常繁琐且容易出错, 你需要给每个对象绑定一个Timer, 同时需要在Timer到期时处理对象, 并且重置Timer的API和设置Timer的API是同一个, 稍有不慎就会搞砸.

现在, 我想出了一种相对简单的实现方式, 虽然精度不是非常理想, 但对于一般应用而言, 足矣.


我们构造一个类, 它有一些私有的数据, 这些可以自定义, 但有一些API是必须的:

class Client
{
private:
// ...Data or something
int32_t m_life;
int32_t m_max_life;
DWORD delete_thread_id;
HANDLE count_thread_handle;
public:
Client(int32_t, DWORD);
void reset(void);
static WIN32API DWORD countDownEntry(void *);
DWORD countDown(void);
// ...De-cons...
}

1. 构造函数:

Client:Client(int32_t life, DWORD thread_id)
{
m_max_life = m_life = life;
delete_thread_id = thread_id;
count_thread_handle = CreateThread(..., ..., Client::countDownEntry, this);
}

第二个参数是用来销毁对象的线程ID, 这样设计是考虑到对象有可能保存在一个堆, 如果我们简单地调用析构函数, 那么对象本身所占据的空间就无法被释放了, 所以我们通知这么一个线程来完成所有的析构操作.

注意到我们使用的是countDownEntry()而不是countDown(), 因为CreateThread不接受一个非静态的成员函数作为函数入口(无法确认地址).

2. reset()方法, 这方法需要先挂起倒计时的线程, 主要是防止同时访问同一个内存的情况出现:

void Client::reset(void)
{
SuspendThread(count_thread_handle);
m_life = m_max_life;
ResumeThread(count_thread_handle);
}

3. countDownEntry()方法为何是static的? 很简单, 我们需要在构造函数里使用它来初始化倒计时线程, 而它的实现非常简单, 我们在构造函数里把this指针传递给这个静态方法, 并在静态方法里重新获取这个this代表的对象, 调用这个对象的倒计时函数即可:

static WIN32API DWORD Client::countDownEntry(void *pM)
{
Client *c = (Client *) pM;
return c->countDown();
}

4. 而countDown()方法更加简单, 使用Sleep函数来计时即可, 每计一秒就将life减1:

DWORD Client::countDown()
{
while (m_life > )
{
Sleep();
m_life--;
}
PostThreadMessageA(delete_thread_id);
return ;
}

以上就是这样一个对象的设计思路, 原理比较简单, 也只是写了个大概, 同时需要windows.h的支持.

[C++] 一个能够定时自毁的类的实现的更多相关文章

  1. 3.实现一个名为Person的类和它的子类Employee,Employee有两个子类Faculty 和Staff。

    23.实现一个名为Person的类和它的子类Employee,Employee有两个子类Faculty 和Staff. 具体要求如下: (1)Person类中的属性有:姓名name(String类型) ...

  2. classmethod一个用处是创建可选类构造器

    Definition and Introduction通常来说, descriptor 是一种绑定着特殊行为属性的对象, 在访问它时行为被descriptor协议定义的方法所重载.这些方法是__get ...

  3. 一天一个Java基础——对象和类

    1.在Java中你所做的全部工作就是定义类,产生那些类的对象,以及发送消息给这些对象 2.可以在类中设置两种类型的元素:字段(也被称作数据成员)和方法(也被称作成员函数) 3.字段可以是任何类型的对象 ...

  4. 一个漂亮的php验证码类

    一个漂亮的php验证码类(分享)   作者: 字体:[增加 减小] 类型:转载 下面小编就为大家分享一个漂亮的php验证码类.需要的朋友可以过来参考下   直接上代码: 复制代码 代码如下: //验证 ...

  5. 设计一个 Java 程序,自定义异常类,从命令行(键盘)输入一个字符串,如果该字符串值为“XYZ”。。。

    设计一个 Java 程序,自定义异常类,从命令行(键盘)输入一个字符串,如果该字符串值为“XYZ”,则抛出一个异常信息“This is a XYZ”,如果从命令行输入 ABC,则没有抛出异常.(只有 ...

  6. CSS一个元素同时使用多个类选择器(class selector)

    CSS类选择器参考手册 一个元素同时使用多个类选择器 CSS中类选择器用点号表示.实际项目中一个div元素为了能被多个样式表匹配到(样式复用),通常div的class中由好几段组成,如<div ...

  7. 定义一个复数(z=x+iy)类Complex,包含: 两个属性:实部x和虚部y 默认构造函数 Complex(),设置x=0,y=0 构造函数:Complex(int i,int j) 显示复数的方法:showComp()将其显示为如: 5+8i或5-8i 的形式。 求两个复数的和的方法:(参数是两个复数类对象,返回值是复数类对象)public Complex addComp(Compl

    因标题框有限,题目未显示完整,以下再放一份: 定义一个复数(z=x+iy)类Complex,包含: 两个属性:实部x和虚部y 默认构造函数 Complex(),设置x=0,y=0 构造函数:Compl ...

  8. Eclipse里选中一个变量后,这个类里的该变量不变色了?

    Eclipse里选一个变量后,这个类里的该变量不变色了. 1.使用“Alt+Shift+O”对该提示功能的开/关切换 2.可以在以下设置选中后的文本提示颜色  window--> Prefere ...

  9. String、StringBuffer和StringBuilder,定义一个自己的StringBuilder的类

    String Java中的字符串值属于String类,虽然有其它方法表示字符串(如字符数组),但Java一般使用String类作为字符串的标准格式,Java编译器把字符串值作为String对象; St ...

随机推荐

  1. 转 解决linux下tomcat的shutdown命令杀不死进程

    tomcat在windows下可以直接关闭,但是貌似在Linux下有时候shutdown.sh 没有关闭tomcat进程; 现象:在Linux下shutdown.sh ,然后查看tomcat进程发现没 ...

  2. 基础的shell脚本

    #! /bin/sha="hello world"echo "A is "   echo $a echo "<br />" ec ...

  3. BUCTOJ1073

    #include "iostream" #include "algorithm" using namespace std; ; struct Time { in ...

  4. Oracle 账户锁定问题解决办法

    1 打开 SQL PLUS 2 登录数据库 3 输入 conn/as sysdba; 4 输入 alter user 数据库名 account unlock;

  5. The working copy needs to be upgraded svn: The working copy at

    错误信息: The working copy needs to be upgradedsvn: The working copy at 'F:\JAVA Project\PAW-VRVEIS-JJ-2 ...

  6. linux分析、诊断及调优的必备“杀器”之一

    下面分别列出linux分析.诊断及调优时用到的工具,并分别进行说明,以方便自己和其他同学参考学习,禁止转载. 1.top top - 02:06:59 up 4 days, 17:14, 2 user ...

  7. angularjs 中的scope继承关系——(1)

    转自:http://www.lovelucy.info/understanding-scopes-in-angularjs.html JavaScript 的原型链继承 假设父类 parentScop ...

  8. webservice 基本要点

    webservice的特点 webservices是自我包含的 webservices是自我描述的 webservices是跨平台和语言的 webservices是基于开放和标准的 webservic ...

  9. AVG Internet Security 2013 – 免费1年

    AVG 是一款来自捷克的老牌的且非常优秀的免费杀毒软件,自推出以来就颇受用户好评!一直以来诸多的优点使其获得不少忠实用户,即便在中国也赢得了不少粉丝!AVG的安全产品广泛地被欧美以及大洋洲地区使用,并 ...

  10. GSM中时隙、信道、突发序列、帧的解释

    刚从论坛中看到有人问GSM中时隙.信道.突发序列.帧知识.今天我们数字通信正好上到这一块,我就根据我知道的和网上搜索的回答! 1.时分多路复用技术 FDMA:频分多址 TDMA:时分多址 CDMA:码 ...