2018-08-19 15:31:26 +08:00
|
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2017-2018 IQIYI
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* AUTHOR(S)
|
|
|
|
|
* Zheng Shuxin
|
|
|
|
|
* E-mail: zhengshuxin@qiyi.com
|
|
|
|
|
*
|
|
|
|
|
* VERSION
|
|
|
|
|
* Thu 07 Sep 2017 04:33:59 PM CST
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
#include "../acl_cpp_define.hpp"
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include "mbox.hpp"
|
|
|
|
|
#include "util.hpp"
|
|
|
|
|
#include "thread.hpp"
|
|
|
|
|
#include "thread_mutex.hpp"
|
|
|
|
|
|
|
|
|
|
namespace acl {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>صĶ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
class trigger_item
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
typedef std::map<long long, trigger_item<T>*> trigger_items_t;
|
|
|
|
|
|
|
|
|
|
trigger_item(trigger_items_t& items) : items_(items) {}
|
|
|
|
|
~trigger_item(void) {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* @pararm o {T*}
|
|
|
|
|
*/
|
|
|
|
|
void add(T* o)
|
|
|
|
|
{
|
|
|
|
|
objs_.push_back(o);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ɾ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>صĶ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* @pararm o {T*}
|
|
|
|
|
* @return {int} <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ >= 0 <EFBFBD><EFBFBD>ʾʣ<EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>صĶ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> -1 <EFBFBD><EFBFBD>ʾ<EFBFBD>ö<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
*/
|
|
|
|
|
int del(T* o)
|
|
|
|
|
{
|
|
|
|
|
for (typename std::vector<T*>::iterator it = objs_.begin();
|
|
|
|
|
it != objs_.end(); ++it) {
|
|
|
|
|
|
|
|
|
|
if (*it == o) {
|
|
|
|
|
objs_.erase(it);
|
|
|
|
|
return (int) objs_.size();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* @return {std::vector<T*>&}
|
|
|
|
|
*/
|
|
|
|
|
std::vector<T*>& get_objs(void)
|
|
|
|
|
{
|
|
|
|
|
return objs_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::vector<T*> objs_;
|
|
|
|
|
trigger_items_t& items_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ὣ<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> T <EFBFBD><EFBFBD>Ҫʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
*
|
|
|
|
|
* bool on_trigger(void); // <20><>ʱʱ<CAB1>䵽<EFBFBD><E4B5BD>ʱ<EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ʾ
|
|
|
|
|
* // <20>Ƿ<EFBFBD><C7B7><EFBFBD>Ҫ<EFBFBD>ٴδ<D9B4><CEB4><EFBFBD><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
|
|
|
|
|
* int get_ttl(void) const; // <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룩
|
|
|
|
|
* void set_key(long long key); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
|
|
|
|
* long long get_key(void) const; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> set_key <20><><EFBFBD>õļ<C3B5>
|
|
|
|
|
*
|
|
|
|
|
* <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> T <EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
|
|
|
|
* class mytask
|
|
|
|
|
* {
|
|
|
|
|
* public:
|
|
|
|
|
* mytask(void) {}
|
|
|
|
|
* ~mytask(void) {}
|
|
|
|
|
*
|
|
|
|
|
* // @override
|
|
|
|
|
* bool on_trigger(void)
|
|
|
|
|
* {
|
|
|
|
|
* return true;
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* // @override
|
|
|
|
|
* int get_ttl(void) const
|
|
|
|
|
* {
|
|
|
|
|
* return 1000;
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* // @override
|
|
|
|
|
* void set_key(long long key)
|
|
|
|
|
* {
|
|
|
|
|
* key_ = key;
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* // @override
|
|
|
|
|
* long long get_key(void) const
|
|
|
|
|
* {
|
|
|
|
|
* return key_;
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* private:
|
|
|
|
|
* long long key_;
|
|
|
|
|
* };
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
class timer_trigger
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
typedef std::map<long long, trigger_item<T>*> trigger_items_t;
|
|
|
|
|
typedef typename trigger_items_t::iterator trigger_iter_t;
|
|
|
|
|
|
|
|
|
|
timer_trigger(void) {}
|
|
|
|
|
~timer_trigger(void) {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* @pararm o {T*}
|
|
|
|
|
*/
|
|
|
|
|
void add(T* o)
|
|
|
|
|
{
|
|
|
|
|
int ttl = o->get_ttl();
|
|
|
|
|
long long key = get_curr_stamp() + ttl;
|
|
|
|
|
|
|
|
|
|
trigger_item<T>* item;
|
|
|
|
|
trigger_iter_t it = items_.find(key);
|
|
|
|
|
if (it == items_.end()) {
|
|
|
|
|
item = new trigger_item<T>(items_);
|
|
|
|
|
items_[key] = item;
|
|
|
|
|
} else
|
|
|
|
|
item = it->second;
|
|
|
|
|
item->add(o);
|
|
|
|
|
o->set_key(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ɾ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> o->get_key() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
|
|
|
|
* @pararm o {T*} ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* @return {int} >= 0 ʱ<EFBFBD><EFBFBD>ʾʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-1 <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
*/
|
|
|
|
|
int del(T* o)
|
|
|
|
|
{
|
|
|
|
|
long long key = o->get_key();
|
|
|
|
|
trigger_iter_t it = items_.find(key);
|
|
|
|
|
|
|
|
|
|
if (it == items_.end())
|
|
|
|
|
return -1;
|
|
|
|
|
if (it->second->del(o) == 0) {
|
|
|
|
|
delete it->second;
|
|
|
|
|
items_.erase(it);
|
|
|
|
|
}
|
|
|
|
|
return (int) items_.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD>ڵĶ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* @return {long long} <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -1
|
|
|
|
|
* <EFBFBD><EFBFBD>ʾû<EFBFBD>ж<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
*/
|
|
|
|
|
long long trigger(void)
|
|
|
|
|
{
|
|
|
|
|
long long key = get_curr_stamp();
|
|
|
|
|
std::vector<trigger_item<T>*> items;
|
|
|
|
|
trigger_iter_t iter;
|
|
|
|
|
for (iter = items_.begin(); iter != items_.end();) {
|
|
|
|
|
if (iter->first > key)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
items.push_back(iter->second);
|
|
|
|
|
items_.erase(iter++);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (typename std::vector<trigger_item<T>*>::iterator
|
|
|
|
|
it = items.begin(); it != items.end(); ++it) {
|
|
|
|
|
|
|
|
|
|
trigger(*it);
|
|
|
|
|
delete *it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iter = items_.begin();
|
|
|
|
|
if (iter == items_.end())
|
|
|
|
|
return -1;
|
|
|
|
|
return iter->first;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
trigger_items_t items_;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD>ʱʱ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* @pararm item {trigger_item<T>*}
|
|
|
|
|
*/
|
|
|
|
|
void trigger(trigger_item<T>* item)
|
|
|
|
|
{
|
|
|
|
|
std::vector<T*>& objs = item->get_objs();
|
|
|
|
|
for (typename std::vector<T*>::iterator it = objs.begin();
|
|
|
|
|
it != objs.end(); ++it) {
|
|
|
|
|
|
|
|
|
|
if (!(*it)->on_trigger())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
int ttl = (*it)->get_ttl();
|
|
|
|
|
long long key = get_curr_stamp() + ttl;
|
|
|
|
|
|
|
|
|
|
trigger_iter_t iter = items_.find(key);
|
|
|
|
|
if (iter == items_.end()) {
|
|
|
|
|
item = new trigger_item<T>(items_);
|
|
|
|
|
items_[key] = item;
|
|
|
|
|
} else
|
|
|
|
|
item = iter->second;
|
|
|
|
|
|
|
|
|
|
item->add(*it);
|
|
|
|
|
(*it)->set_key(key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̴߳<EFBFBD> mbox <EFBFBD>л<EFBFBD><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>붨ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>Ȼ<EFBFBD><EFBFBD>
|
|
|
|
|
* <EFBFBD><EFBFBD>ʱ<EFBFBD>Ӵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
class thread_trigger : public thread
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
thread_trigger(void)
|
|
|
|
|
: delay_(100) // <20><>ʼ<EFBFBD><CABC>ʱ<EFBFBD>ij<EFBFBD>ʱ<EFBFBD>ȴ<EFBFBD>ʱ<EFBFBD>䣨<EFBFBD><E4A3A8><EFBFBD>룩
|
|
|
|
|
, stop_(false) // <20>Ƿ<EFBFBD>ֹͣ<CDA3>߳<EFBFBD>
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ~thread_trigger(void) {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* @pararm o {T*}
|
|
|
|
|
*/
|
|
|
|
|
void add(T* o)
|
|
|
|
|
{
|
|
|
|
|
mbox_.push(o);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫɾ<EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD>֮
|
|
|
|
|
* @pararm o {T*}
|
|
|
|
|
*/
|
|
|
|
|
void del(T* o)
|
|
|
|
|
{
|
|
|
|
|
lock_.lock();
|
|
|
|
|
timer_del_.push_back(o);
|
|
|
|
|
lock_.unlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
timer_trigger<T>& get_trigger(void)
|
|
|
|
|
{
|
|
|
|
|
return timer_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// @override
|
|
|
|
|
void* run(void)
|
|
|
|
|
{
|
|
|
|
|
while (!stop_) {
|
|
|
|
|
T* o = mbox_.pop(delay_);
|
|
|
|
|
if (o)
|
|
|
|
|
timer_.add(o);
|
|
|
|
|
|
|
|
|
|
long long next = timer_.trigger();
|
|
|
|
|
long long curr = get_curr_stamp();
|
|
|
|
|
if (next == -1)
|
|
|
|
|
delay_ = 100;
|
|
|
|
|
else {
|
|
|
|
|
delay_ = next - curr;
|
|
|
|
|
if (delay_ < 0)
|
|
|
|
|
delay_ = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lock_.lock();
|
|
|
|
|
typename std::vector<T*>::iterator it;
|
|
|
|
|
for (it = timer_del_.begin();
|
|
|
|
|
it != timer_del_.end(); ++it) {
|
|
|
|
|
|
|
|
|
|
timer_.del(*it);
|
|
|
|
|
}
|
|
|
|
|
timer_del_.clear();
|
|
|
|
|
lock_.unlock();
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
long long delay_;
|
|
|
|
|
bool stop_;
|
|
|
|
|
|
|
|
|
|
timer_trigger<T> timer_;
|
|
|
|
|
mbox<T> mbox_;
|
|
|
|
|
|
|
|
|
|
std::vector<T*> timer_del_;
|
|
|
|
|
thread_mutex lock_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace acl
|