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

View File

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

View File

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

View File

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

View File

@ -10,80 +10,19 @@ void e2d::TimerManager::__update()
if (s_vTimers.empty() || Game::isPaused()) if (s_vTimers.empty() || Game::isPaused())
return; 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; std::vector<Timer*>::iterator mIter;
for (mIter = s_vTimers.begin(); mIter != s_vTimers.end();) 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); mIter = s_vTimers.erase(mIter);
} }
else 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) for (auto timer : s_vTimers)
{ {
if (timer->getParentNode() == pParentNode) if (timer->getName() == name)
{ {
timer->start(); 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) for (auto timer : s_vTimers)
{ {
if (timer->getParentNode() == pParentNode) if (timer->getName() == name)
{ {
timer->stop(); 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 (timer->getName() == name)
if (t->getParentNode() == pParentNode)
{ {
SafeRelease(&t); return timer;
s_vTimers.erase(s_vTimers.begin() + i);
}
else
{
i++;
} }
} }
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() void e2d::TimerManager::__resetAllTimers()
@ -158,12 +164,11 @@ void e2d::TimerManager::__resetAllTimers()
} }
} }
void e2d::TimerManager::startAllTimers() void e2d::TimerManager::__uninit()
{ {
TimerManager::startAllTimersBindedWith(SceneManager::getCurrentScene()); for (const auto timer : s_vTimers)
} {
timer->release();
void e2d::TimerManager::stopAllTimers() }
{ s_vTimers.clear();
TimerManager::stopAllTimersBindedWith(SceneManager::getCurrentScene());
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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