大佬教程收集整理的这篇文章主要介绍了Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
#include <functional> #include <mutex> #include <set> #include "CCRef.h" #include CCVector.huthash.h" NS_CC_BEGIN /** * @addtogroup global * @{ */ class scheduler; typedef std::function<void(float)> ccschedulerFunc;
class CC_DLL Timer : public Ref { protected: Timer(); public: * get interval in seconds */ inline float geTinterval() const { return _interval; }; * set interval in seconds void seTinterval(float interval) { _interval = interval; }; void setupTimerWithInterval(float seconds,unsigned int repeat,float delay); virtual void trigger() = 0; void cancel() = 0; * triggers the timer */ void update(float dt); protected: scheduler* _scheduler; // weak ref float _elapsed; bool _runForever; bool _useDelay; unsigned int _timesExecuted; unsigned int _repeat; 0 = once,1 is 2 x executed float _delay; float _interval; };
#define kRepeatForever (UINT_MAX -1)
Ref* _target;
scheduler::scheduler(void) : _timeScale(1.0f),_updatesNegList(nullptr),_updates0List(nullptr),_updatesPosList(nullptr),_hashForupdates(nullptr),_hashForTimers(nullptr),_currentTarget(nullptr),_currentTargetSalvaged(false),_updateHashLocked(false) #if CC_ENABLE_SCRIPT_BINDING,_scriptHandlerEntries(20) #endif { I don't expect to have more than 30 functions to all per frame _functionsToPerform.reserve(30); } scheduler::~scheduler(void) { unscheduleAll(); }
ccArrayEnsureExtraCapacity(element->timers,1);
@H_616_1@这行代码是给 ccArray分配内存,确定能再容纳一个timer.
@H_616_1@函数的最后四行代码,就是创建了一个新的 TimerTargetSELEctor 对象,并且对其赋值 还加到了 定时器列表里。
@H_616_1@这里注意一下,调用了 timer->release() 减少了一次引用,会不会造成timer被释放呢?当然不会了,大家看一下ccArrayAppendObject方法里面已经对 timer进行了一次retain操作所以 调用了一次release后保证 timer的引用计数为1.
@H_616_1@看过这个方法,我们清楚了几点
// currentTimerSalvaged的作用是标记当前这个定时器是否已经失效,在设置失效的时候我们对定时器增加过一次引用记数,这里调用release来减少那次引用记数,这样释放很安全,这里用到了这个小技巧,延迟释放,这样后面的程序不会出现非法引用定时器指针而出现错误 elt->currentTimer->release(); } // currentTimer指针使用完了,设置成空指针 elt->currentTimer = nullptr; } } elt,at this moment,is still valid so it is safe to ask this here (issue #490)
// 因为下面有可能要清除这个对象currentTarget为了循环进行下去,这里先在currentTarget对象还存活的状态下找到链表的下一个指针。 elt = (tHashTimerEntry *)elt->hh.next; only delete currentTarget if no actions were scheduled during the cycle (issue #481)
如果_currentTartetSalvaged 为 true 且这个对象里面的定时器列表为空那么这个对象就没有计时任务了我们要把它从__hashForTimers列表里面删除。 if (_currentTargetSalvaged && _currentTarget->timers->num == 0) { removeHasHelement(_currentTarget); } } 下面这三个循环也是清理工作 updates with priority < 0 DL_FOREACH_SAFE(_updatesNegList,255); line-height:1.5!important">if (entry->@H_287_13@markedFordeletion) { this->removeupdateFromHash(entry); } } updates with priority == 0 DL_FOREACH_SAFE(_updates0List,0); line-height:1.5!important"> updates with priority > 0 DL_FOREACH_SAFE(_updatesPosList,255); line-height:1.5!important">this->removeupdateFromHash(entry); } } _updateHashLocked = false; _currentTarget = nullptr; #if CC_ENABLE_SCRIPT_BINDING Script callBACks Iterate over all the script callBACks if (!_scriptHandlerEntries.empty()) { for (auto i = _scriptHandlerEntries.size() - 1; i >= 0; i--) { schedulerScriptHandlerEntry* eachEntry = _scriptHandlerEntries.at(i); if (eachEntry->ismarkedFordeletion()) { _scriptHandlerEntries.erase(i); } else if (!eachEntry->isPaused()) { eachEntry->getTimer()->update(dt); } } } #endif 上面都是对象的定时任务,这里是多线程处理函数的定时任务。 TesTing size is faster than locking / unlocking. And almost never there will be functions scheduled to be called. 这块作者已经说明了,函数的定时任务不常用。我们简单了解一下就可了。 if( !_functionsToPerform.empty() ) { _performMutex.lock(); fixed #4123: Save the callBACk functions,they must be invoked after '_performMutex.unlock()',otherwise if new functions are added in callBACk,it will cause thread deadlock. auto temp = _functionsToPerform; _functionsToPerform.clear(); _performMutex.unlock(); for( const auto &function : temp ) { function(); } } }
* 根据key与target 指针来判断是否这个对象的这个key的定时器在scheduled里面控制。 bool isscheduled(void *target); * 同上,只不过判断条件不一样。. @since v3.0 bool isscheduled(SEL_scheDULE SELEctor,Ref *target); ///////////////////////////////////// * 暂停一个对象的所有定时器 void pauseTarget(void *target); * 恢复一个对象的所有定时器 void resumeTarget(* 询问一个对象的定时器是不是暂停状态 bool isTargetPaused(* 暂停所有对象的定时器 */ std::set<void*> pauseAllTargets(); * 根据权重值来暂停所有对象的定时器 void*> pauseAllTargetsWithMinPriority(int minPriority); * 恢复描写对象的定时器暂停状态。 void resumeTargets(void*>& targetsToResumE); * 将一个函数定时器加入到调度管理器里面。 这也是update函数中最后处理的那个函数列表里的函数 任务增加的接口。 void performFunctionInCocosThread( const std::function<void()> &function);
template <class T> void scheduleupdate(T *target,255); line-height:1.5!important">int priority,255); line-height:1.5!important">bool paused) { this->schedulePerFrame([target](float dt){ target->update(dt); },paused); }
以上是大佬教程为你收集整理的Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析全部内容,希望文章能够帮你解决Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。