significant update about Timer class

This commit is contained in:
Nomango 2018-03-03 17:02:08 +08:00
parent 627f04d7ce
commit 05450175a3
12 changed files with 213 additions and 223 deletions

View File

@ -115,7 +115,7 @@ int e2d::Game::run()
}
else
{
ObjectManager::__clearObjects(); // 刷新内存池
ObjectManager::__update(); // 刷新内存池
Time::__sleep(); // 挂起线程
}
}
@ -159,12 +159,14 @@ void e2d::Game::uninit()
Input::__uninit();
// 关闭播放器
MusicManager::__uninit();
// 清空定时器
TimerManager::__uninit();
// 恢复计时操作
Time::__uninit();
// 清空图片缓存
Image::clearCache();
// 刷新内存池
ObjectManager::__clearObjects();
ObjectManager::__clearAllObjects();
// 删除渲染相关资源
Renderer::__discardResources();
// 销毁窗口

View File

@ -25,3 +25,8 @@ void e2d::Object::release()
// 通知对象管理池刷新
ObjectManager::clear();
}
int e2d::Object::getReferenceCount() const
{
return m_nRefCount;
}

View File

@ -3,7 +3,6 @@
#include "..\emanagers.h"
#include "..\etools.h"
#include "..\eactions.h"
#include <algorithm>
e2d::Scene::Scene()
: m_bWillSave(true)

View File

@ -2,18 +2,18 @@
#include "..\ebase.h"
// ObjectManager 释放池的实现机制:
// EObject 类中的引用计数m_nRefCount保证了指针的使用安全
// Object 类中的引用计数m_nRefCount保证了指针的使用安全
// 它记录了对象被使用的次数,当计数为 0 时ObjectManager 会自动释放这个对象
// 所有的 EObject 对象都应在被使用时(例如 Text 添加到了场景中)
// 所有的 Object 对象都应在被使用时(例如 Text 添加到了场景中)
// 调用 retain 函数保证该对象不被删除,并在不再使用时调用 release 函数
// 让其自动释放
// 释放池容器
static std::vector<e2d::Object*> s_vPool;
// 对象管理池
static std::vector<e2d::Object*> s_vObjectPool;
// 标志释放池执行状态
static bool s_bNotifyed = false;
void e2d::ObjectManager::__clearObjects()
void e2d::ObjectManager::__update()
{
if (!s_bNotifyed) return;
@ -21,14 +21,14 @@ void e2d::ObjectManager::__clearObjects()
// 创建迭代器
static std::vector<e2d::Object*>::iterator iter;
// 循环遍历容器中的所有对象
for (iter = s_vPool.begin(); iter != s_vPool.end();)
for (iter = s_vObjectPool.begin(); iter != s_vObjectPool.end();)
{
if ((*iter)->m_nRefCount <= 0)
if ((*iter)->getReferenceCount() <= 0)
{
// 若对象的引用的计数小于等于 0, 释放该对象
delete (*iter);
// 从释放池中删除该对象
iter = s_vPool.erase(iter);
iter = s_vObjectPool.erase(iter);
}
else
{
@ -37,12 +37,21 @@ void e2d::ObjectManager::__clearObjects()
}
}
void e2d::ObjectManager::__clearAllObjects()
{
for (const auto &obj : s_vObjectPool)
{
delete obj;
}
s_vObjectPool.clear();
}
void e2d::ObjectManager::add(e2d::Object * nptr)
{
if (!nptr->m_bManaged)
{
nptr->m_bManaged = true;
s_vPool.push_back(nptr); // 将一个对象放入释放池中
s_vObjectPool.push_back(nptr); // 将一个对象放入释放池中
}
}

View File

@ -155,6 +155,7 @@ bool e2d::SceneManager::__init()
if (!s_pNextScene)
{
s_pNextScene = new Scene();
s_pNextScene->retain();
}
s_pCurrentScene = s_pNextScene;

View File

@ -10,80 +10,19 @@ void e2d::TimerManager::__update()
if (s_vTimers.empty() || Game::isPaused())
return;
for (auto &timer : s_vTimers)
{
if (timer->_isReady())
{
timer->_callOn();
}
}
}
void e2d::TimerManager::add(double timeOut, TimerCallback callback)
{
auto pTimer = new Timer(callback, timeOut, 0, false);
TimerManager::add(pTimer, SceneManager::getCurrentScene());
}
void e2d::TimerManager::add(Timer * pTimer, Scene * pParentScene)
{
WARN_IF(pParentScene == nullptr, "Bind Timer with a NULL Scene pointer!");
if (pParentScene)
{
TimerManager::add(pTimer, pParentScene->getRoot());
}
}
void e2d::TimerManager::add(Timer * pTimer, Node * pParentNode)
{
WARN_IF(pTimer == nullptr, "Timer NULL pointer exception!");
WARN_IF(pParentNode == nullptr, "Bind Timer with a NULL Node pointer!");
if (pTimer && pParentNode)
{
ASSERT(
pTimer->m_pParentNode != nullptr,
"The timer is already binded, cannot be binded again!"
);
pTimer->start();
pTimer->retain();
pTimer->m_pParentNode = pParentNode;
s_vTimers.push_back(pTimer);
}
}
void e2d::TimerManager::startTimers(const String & name)
{
for (auto timer : s_vTimers)
{
if (timer->getName() == name)
{
timer->start();
}
}
}
void e2d::TimerManager::stopTimers(const String & name)
{
for (auto timer : s_vTimers)
{
if (timer->getName() == name)
{
timer->stop();
}
}
}
void e2d::TimerManager::deleteTimers(const String & name)
{
std::vector<Timer*>::iterator mIter;
for (mIter = s_vTimers.begin(); mIter != s_vTimers.end();)
{
if ((*mIter)->getName() == name)
Timer * pTimer = (*mIter);
// 更新定时器
if (pTimer->isReady())
{
SafeRelease(&(*mIter));
pTimer->update();
}
// 清除不必要的定时器
if (pTimer->m_bClear)
{
pTimer->release();
mIter = s_vTimers.erase(mIter);
}
else
@ -93,61 +32,128 @@ void e2d::TimerManager::deleteTimers(const String & name)
}
}
void e2d::TimerManager::startAllTimersBindedWith(Scene * pParentScene)
void e2d::TimerManager::add(double timeOut, TimerCallback callback)
{
TimerManager::startAllTimersBindedWith(pParentScene->getRoot());
auto pTimer = new Timer(L"", callback, timeOut, 1, false, true);
pTimer->start();
}
void e2d::TimerManager::stopAllTimersBindedWith(Scene * pParentScene)
void e2d::TimerManager::add(Timer * pTimer)
{
TimerManager::stopAllTimersBindedWith(pParentScene->getRoot());
WARN_IF(pTimer == nullptr, "Timer NULL pointer exception!");
if (pTimer)
{
auto findTimer = [](Timer * pTimer) -> bool
{
for (const auto &t : s_vTimers)
{
if (pTimer == t)
{
return true;
}
}
return false;
};
bool bHasTimer = findTimer(pTimer);
WARN_IF(bHasTimer, "The timer is already added, cannot be added again!");
if (!bHasTimer)
{
pTimer->retain();
s_vTimers.push_back(pTimer);
}
}
}
void e2d::TimerManager::startAllTimersBindedWith(Node * pParentNode)
void e2d::TimerManager::start(const String & name)
{
for (auto timer : s_vTimers)
{
if (timer->getParentNode() == pParentNode)
if (timer->getName() == name)
{
timer->start();
}
}
for (auto child = pParentNode->getChildren().begin(); child != pParentNode->getChildren().end(); child++)
{
TimerManager::startAllTimersBindedWith((*child));
}
}
void e2d::TimerManager::stopAllTimersBindedWith(Node * pParentNode)
void e2d::TimerManager::stop(const String & name)
{
for (auto timer : s_vTimers)
{
if (timer->getParentNode() == pParentNode)
if (timer->getName() == name)
{
timer->stop();
}
}
for (auto child : pParentNode->getChildren())
}
void e2d::TimerManager::stopAndClear(const String & name)
{
for (auto timer : s_vTimers)
{
TimerManager::stopAllTimersBindedWith(child);
if (timer->getName() == name)
{
timer->stopAndClear();
}
}
}
void e2d::TimerManager::__clearAllTimersBindedWith(Node * pParentNode)
e2d::Timer * e2d::TimerManager::get(const String & name)
{
for (size_t i = 0; i < s_vTimers.size();)
for (auto timer : s_vTimers)
{
auto t = s_vTimers[i];
if (t->getParentNode() == pParentNode)
if (timer->getName() == name)
{
SafeRelease(&t);
s_vTimers.erase(s_vTimers.begin() + i);
}
else
{
i++;
return timer;
}
}
return nullptr;
}
std::vector<e2d::Timer*> e2d::TimerManager::getTimers(const String & name)
{
std::vector<Timer*> vTimers;
for (auto timer : s_vTimers)
{
if (timer->getName() == name)
{
vTimers.push_back(timer);
}
}
return std::move(vTimers);
}
void e2d::TimerManager::startAllTimers()
{
for (auto timer : s_vTimers)
{
timer->start();
}
}
void e2d::TimerManager::stopAllTimers()
{
for (auto timer : s_vTimers)
{
timer->stop();
}
}
void e2d::TimerManager::stopAndClearAllTimers()
{
for (auto timer : s_vTimers)
{
timer->stop();
timer->release();
}
s_vTimers.clear();
}
std::vector<e2d::Timer*> e2d::TimerManager::getAllTimers()
{
return s_vTimers;
}
void e2d::TimerManager::__resetAllTimers()
@ -158,12 +164,11 @@ void e2d::TimerManager::__resetAllTimers()
}
}
void e2d::TimerManager::startAllTimers()
void e2d::TimerManager::__uninit()
{
TimerManager::startAllTimersBindedWith(SceneManager::getCurrentScene());
}
void e2d::TimerManager::stopAllTimers()
{
TimerManager::stopAllTimersBindedWith(SceneManager::getCurrentScene());
for (const auto timer : s_vTimers)
{
timer->release();
}
s_vTimers.clear();
}

View File

@ -40,7 +40,6 @@ e2d::Node::Node()
e2d::Node::~Node()
{
TimerManager::__clearAllTimersBindedWith(this);
ActionManager::__clearAllActionsBindedWith(this);
ShapeManager::__delShape(m_pShape);
for (auto child : m_vChildren)
@ -637,9 +636,6 @@ e2d::Node * e2d::Node::getChild(const String & name)
std::vector<e2d::Node*> e2d::Node::getChildren(const String & name)
{
std::vector<Node*> vChildren;
WARN_IF(name.isEmpty(), "Invalid Node name.");
unsigned int hash = name.getHashCode();
for (auto child : m_vChildren)

View File

@ -5,45 +5,25 @@
e2d::Timer::Timer()
: m_bRunning(false)
, m_nRunTimes(0)
, m_pParentNode(nullptr)
, m_Callback(nullptr)
, m_fInterval(0)
, m_fLast(0)
, m_nRepeatTimes(-1)
, m_nUpdateTimes(-1)
, m_bAtOnce(false)
, m_bAutoRelease(false)
, m_bClear(false)
{
TimerManager::add(this);
}
e2d::Timer::Timer(const TimerCallback & callback, double interval /* = 0 */, int repeatTimes /* = -1 */, bool atOnce /* = false */)
: m_bRunning(false)
, m_nRunTimes(0)
, m_pParentNode(nullptr)
, m_Callback(nullptr)
, m_fInterval(0)
, m_fLast(0)
, m_nRepeatTimes(-1)
, m_bAtOnce(false)
{
this->setCallback(callback);
this->setRepeatTimes(repeatTimes);
this->setInterval(interval);
m_bAtOnce = atOnce;
}
e2d::Timer::Timer(const String & name, const TimerCallback & callback, double interval /* = 0 */, int repeatTimes /* = -1 */, bool atOnce /* = false */)
: m_bRunning(false)
, m_nRunTimes(0)
, m_pParentNode(nullptr)
, m_Callback(nullptr)
, m_fInterval(0)
, m_fLast(0)
, m_nRepeatTimes(-1)
, m_bAtOnce(false)
e2d::Timer::Timer(const String & name, const TimerCallback & callback, double interval /* = 0 */, int repeatTimes /* = -1 */, bool atOnce /* = false */, bool autoRelease /* = false */)
: Timer()
{
this->setName(name);
this->setCallback(callback);
this->setRepeatTimes(repeatTimes);
this->setUpdateTimes(repeatTimes);
this->setInterval(interval);
m_bAutoRelease = autoRelease;
m_bAtOnce = atOnce;
}
@ -57,6 +37,12 @@ void e2d::Timer::stop()
m_bRunning = false;
}
void e2d::Timer::stopAndClear()
{
m_bRunning = false;
m_bClear = true;
}
void e2d::Timer::start()
{
m_bRunning = true;
@ -68,11 +54,6 @@ e2d::String e2d::Timer::getName() const
return m_sName;
}
e2d::Node * e2d::Timer::getParentNode() const
{
return m_pParentNode;
}
void e2d::Timer::setName(const String & name)
{
m_sName = name;
@ -88,9 +69,9 @@ void e2d::Timer::setCallback(const TimerCallback & callback)
m_Callback = callback;
}
void e2d::Timer::setRepeatTimes(int repeatTimes)
void e2d::Timer::setUpdateTimes(int repeatTimes)
{
m_nRepeatTimes = repeatTimes;
m_nUpdateTimes = repeatTimes;
}
void e2d::Timer::setRunAtOnce(bool bAtOnce)
@ -98,9 +79,9 @@ void e2d::Timer::setRunAtOnce(bool bAtOnce)
m_bAtOnce = bAtOnce;
}
void e2d::Timer::_callOn()
void e2d::Timer::update()
{
if (m_Callback)
if (m_Callback && m_nRunTimes < m_nUpdateTimes)
{
m_Callback();
}
@ -108,17 +89,22 @@ void e2d::Timer::_callOn()
m_nRunTimes++;
m_fLast += m_fInterval;
if (m_nRunTimes == m_nRepeatTimes)
if (m_nRunTimes >= m_nUpdateTimes)
{
this->stop();
if (m_bAutoRelease)
{
this->stopAndClear();
}
else
{
this->stop();
}
}
}
bool e2d::Timer::_isReady() const
bool e2d::Timer::isReady() const
{
if (m_bRunning &&
m_pParentNode &&
m_pParentNode->getParentScene() == SceneManager::getCurrentScene())
if (m_bRunning)
{
if (m_bAtOnce && m_nRunTimes == 0)
return true;

View File

@ -403,6 +403,9 @@ public:
// 引用计数减一
void release();
// 获取引用计数
int getReferenceCount() const;
private:
int m_nRefCount;
bool m_bManaged;
@ -666,7 +669,7 @@ typedef VoidFunction TimerCallback;
typedef VoidFunction ButtonCallback;
#ifndef CreateCallback
#define CreateCallback(Func) std::bind(&Func, this)
#define CreateCallback(func, pointer) std::bind(&func, pointer)
#endif

View File

@ -31,8 +31,11 @@ public:
static void clear();
private:
// 释放引用计数为 0 的对象
static void __clearObjects();
// 更新对象管理器
static void __update();
// 清空所有对象
static void __clearAllObjects();
};
@ -86,16 +89,9 @@ class TimerManager
friend Node;
public:
// 添加一个定时器,并将它绑定到场景
// 添加一个定时器
static void add(
Timer * pTimer,
Scene * pParentScene
);
// 添加一个定时器,并将它绑定到节点
static void add(
Timer * pTimer,
Node * pParentNode
Timer * pTimer
);
// 等待一段时间后执行指定函数
@ -105,38 +101,28 @@ public:
);
// 启动具有相同名称的定时器
static void startTimers(
static void start(
const String &name
);
// 停止具有相同名称的定时器
static void stopTimers(
static void stop(
const String &name
);
// 删除具有相同名称的定时器
static void deleteTimers(
static void stopAndClear(
const String &name
);
// 启动绑定在场景及其子节点上的所有定时器
static void startAllTimersBindedWith(
Scene * pParentScene
// 获取名称相同的定时器(有多个时返回第一个)
static Timer * get(
const String & name
);
// 停止绑定在场景及其子节点上的所有定时器
static void stopAllTimersBindedWith(
Scene * pParentScene
);
// 启动绑定在节点上的所有定时器
static void startAllTimersBindedWith(
Node * pParentNode
);
// 停止绑定在节点上的所有定时器
static void stopAllTimersBindedWith(
Node * pParentNode
// 获取名称相同的定时器
static std::vector<Timer*> getTimers(
const String & name
);
// 启动所有定时器
@ -145,17 +131,21 @@ public:
// 停止所有定时器
static void stopAllTimers();
// 停止并清除所有定时器
static void stopAndClearAllTimers();
// 获取所有定时器
static std::vector<Timer*> getAllTimers();
private:
// 更新定时器
static void __update();
// 清空绑定在节点上的所有定时器
static void __clearAllTimersBindedWith(
Node * pParentNode
);
// 重置定时器状态
static void __resetAllTimers();
// 清空定时器
static void __uninit();
};

View File

@ -49,19 +49,13 @@ class Timer :
public:
Timer();
Timer(
const TimerCallback &callback, /* 定时器回调函数 */
double interval = 0, /* 时间间隔(秒) */
int repeatTimes = -1, /* 定时器执行次数 */
bool atOnce = false /* 是否立即执行 */
);
Timer(
const String &name, /* 定时器名称 */
const TimerCallback &callback, /* 定时器回调函数 */
double interval = 0, /* 时间间隔(秒) */
int repeatTimes = -1, /* 定时器执行次数 */
bool atOnce = false /* 是否立即执行 */
int times = -1, /* 执行次数(设 -1 为永久执行) */
bool atOnce = false, /* 是否立即执行 */
bool autoRelease = false /* 自动清除 */
);
// 启动定时器
@ -70,23 +64,29 @@ public:
// 停止定时器
void stop();
// 停止并清除该定时器
void stopAndClear();
// 更新定时器
void update();
// 获取定时器状态
bool isRunning() const;
// 判断是否达到执行状态
bool isReady() const;
// 获取定时器名称
String getName() const;
// 获取定时器所在节点
Node * getParentNode() const;
// 设置定时器名称
void setName(
const String &name
);
// 设置定时器执行间隔(秒)
// 设置定时器执行间隔
void setInterval(
double interval
double fInterval /* 时间间隔(秒) */
);
// 设置定时器回调函数
@ -94,9 +94,9 @@ public:
const TimerCallback & callback
);
// 设置定时器重复执行次数
void setRepeatTimes(
int nRepeatTimes
// 设置定时器执行次数
void setUpdateTimes(
int nUpdateTimes /* 执行次数(设 -1 为永久执行) */
);
// 设置定时器在绑定后立即执行一次
@ -104,22 +104,16 @@ public:
bool bAtOnce
);
protected:
// 执行回调函数
void _callOn();
// 判断是否达到执行状态
bool _isReady() const;
protected:
String m_sName;
bool m_bRunning;
bool m_bAtOnce;
bool m_bAutoRelease;
bool m_bClear;
int m_nRunTimes;
int m_nRepeatTimes;
int m_nUpdateTimes;
double m_fInterval;
double m_fLast;
Node * m_pParentNode;
TimerCallback m_Callback;
};

View File

@ -101,7 +101,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>None</DebugInformationFormat>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>