c++11 支持lambda 回调
支持无锁多线程操作,cancel 返回true时有一定概率无法取消func的执行
.h文件
#pragma once
#include <map>
#include <process.h>
#include <windows.h>
#include <functional>
#include <atomic>
void Polling(void* ptr);
struct _GTimer_Arg
{
int time=-1;
std::function<void*(void*)> func=NULL;
void* arg = NULL;//此处必须指向堆
int status = 1;
};
class GTimer
{
int _thread;
std::map<int, _GTimer_Arg> _map;
std::atomic_uint32_t _id ;
public:
GTimer()
{
_beginthread(Polling, 0, &_map);
}
unsigned int Set(_GTimer_Arg unit)
{
_map[_id] = unit;
return _id++;
}
int Get(int id)
{
if (_map.count(id))
{
return _map[id].time;
}
return -1;
}
bool TryCancel(int id)//成功返回true,回调不会执行,否则false
{
if (_map.count(id)&&_map[id].time>0)
{
_map[id].status = 2;
return true;
}
return false;
}
};
.cpp
#include "gtimer.h"
void Polling(void* ptr)
{
std::map<int, _GTimer_Arg>* _map = (std::map<int, _GTimer_Arg>*)ptr;
while (true)
{
for (auto iter = _map->begin(); iter != _map->end();)
{ iter->second.time--;
if(iter->second.status==2)
{
if (iter->second.arg != NULL)
{
delete iter->second.arg;
iter->second.arg = NULL;
}
_map->erase(iter++);
continue;
}
if (iter->second.time == 0)
{
if(iter->second.func!=NULL)
iter->second.func(iter->second.arg);
if (iter->second.arg != NULL)
{
delete iter->second.arg;
iter->second.arg = NULL;
}
_map->erase(iter++);
}
else
{
++iter;
}
}
Sleep(1000);
}
}
此版本为线程安全版且增添键模板,线程进入for之前,cancel可立即取消
atomic_lock.h
#pragma once
#include <atomic>
#include <windows.h>
class Atomic_Lock
{
std::atomic_bool _lock = false;
bool _lockExp = true;
bool _unlockExp = false;
int status = 1;
public:
void Lock()
{
while (!atomic_compare_exchange_weak(&_lock, &_unlockExp, _lockExp))
{
Sleep(1);
}
}
void UnLock()
{
_lock = false;
}
void Discard()
{
status = 0;
}
int GetStatus() const
{
return status;
}
};
safeMap.h
#pragma once
#include <map>
#include "atomic_lock.h"
using namespace std;
template <class K,class V>
class safeMap:public map<K,V>
{
Atomic_Lock _al;
public:
safeMap()
{
}
void Lock()
{
_al.Lock();
}
void UnLock()
{
_al.UnLock();
}
};
gtimer.h
#pragma once
#include <process.h>
#include <windows.h>
#include <functional>
#include "safeMap.h"
template <typename T>
void Polling(void* ptr)
{
GTimer<T>* gt = (GTimer<T>*)ptr;
gt->Dealing();
}
struct _GTimer_Arg
{
int time=-1;
std::function<void*(void*)> func=NULL;
void* arg = NULL;
};
template <typename K>
class GTimer
{
int _thread;
safeMap<K, _GTimer_Arg> _map;
public:
void Dealing()
{
while (true)
{
_map.Lock();
for (auto iter = _map.begin(); iter != _map.end();)
{
iter->second.time--;
if (iter->second.time == 0)
{
if (iter->second.func != NULL)
iter->second.func(iter->second.arg);
if (iter->second.arg != NULL) {
int arg_num = _msize(iter->second.arg) / 8;
if (arg_num > 1)
{
void** args = (void**)iter->second.arg;
for (int i = 0; i < arg_num; i++)
{
delete args[i];
}
}
delete iter->second.arg;
}
_map.erase(iter++);
}
else
{
++iter;
}
}
_map.UnLock();
Sleep(1000);
}
}
GTimer()
{
_thread=_beginthread(Polling<K>, 0, this);
}
void Set(K id,_GTimer_Arg unit)
{
_map.Lock();
if(_map.count(id))
{
_GTimer_Arg& ga=_map[id];
if(ga.arg != NULL) {
int arg_num = _msize(ga.arg) / 8;
if (arg_num > 1)
{
void** args = (void**)ga.arg;
for (int i = 0; i < arg_num; i++)
{
delete args[i];
}
}
delete ga.arg;
}
}
_map[id] = unit;
_map.UnLock();
}
int Get(K id)
{
if (_map.count(id))
{
return _map[id].time;
}
return -1;
}
void Cancel(K id)
{
_map.Lock();
if (_map.count(id))
{
_GTimer_Arg& ga = _map[id];
if (ga.arg != NULL) {
int arg_num = _msize(ga.arg) / 8;
if (arg_num > 1)
{
void** args = (void**)ga.arg;
for (int i = 0; i < arg_num; i++)
{
delete args[i];
}
}
delete ga.arg;
}
}
_map.erase(id);
_map.UnLock();
}
};