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

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

这种需求其实是有的, 比如在电影里, 主角知道了一个反派不希望被揭露的秘密, 同时需要保住自己的性命, 那么就可以构造这样一个对象, 如果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. bzoj3262: 陌上花开 三维偏序cdq分治

    三维偏序裸题,cdq分治时,左侧的x一定比右侧x小,然后分别按y排序,对于左侧元素按y大小把z依次插入到树状数组里,其中维护每个左侧元素对右侧元素的贡献,在bit查询即可 /************* ...

  2. thinkphp关于时间加减几天

    1.当前时间,往后退5天: date('Y-m-d H:i:s',strtotime('-1 days')); 2.有固定时间,往后面退一天或者七天,或者30天: 比如时间:$time = 2014- ...

  3. ASP.NET简介

    1.什么是ASP.NET? ASP.NET是一套免费的网络架构,是为了构建一个伟大的或者说非常不错的网站或网络应用,并同时使用了一些前端技术,比如说HTML,CSS和JavaScript ASP.NE ...

  4. EBS标准的查看供应商地点

    VO数据源:oracle.apps.pos.supplier.server.SitesVO SELECT pvsa.address_style, hzl.language, pvsa.province ...

  5. vim 缩进设置

    1.在自己的家目录(/home)下建立.vimrc文件.控制台输入vi ~/.vimrc 回车. 2.在.vimrc文件中输入如下文本: set tabstop=4 set softtabstop= ...

  6. OC NSNumber和NSValue和NSDate和NSData

    一 NSNumber // // main.m // 07-NSNumber // // Created by apple on 13-8-12. // Copyright (c) 2013年 itc ...

  7. mysql创建索引-----高性能(五)

    转载地址:https://www.cnblogs.com/llzhang123/p/7889382.html 索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或 ...

  8. vscode使用集

    abotteram.typescript-react-snippets-0.1.9akamud.vscode-javascript-snippet-pack-0.1.5alechp.react-too ...

  9. hdu6153

    题解: EX_KMP 先计算出ex数组 然后ans统计前缀 然后乘一下就好了 代码: #include<cstdio> #include<cmath> #include< ...

  10. stringBuild置空方法

    参看连接:http://blog.csdn.net/roserose0002/article/details/6972391