从零开始のcocos2dx生活(三)Scheduler

取模

对-1取模是现将-1加上除数的整数倍大于零后再取模。

Timer()

变量

		float _elapsed;              // 渡过的时间.
    bool _runForever;            // 状态变量,标记是否永远的运行。
    bool _useDelay;              // 状态变量,标记是否使用延迟
    unsigned int _timesExecuted; // 记录已经执行了多少次。
    unsigned int _repeat;        // 定义要执行的总次数,0为1次  1为2次 ……
    float _delay;                // 延迟多少秒,是指在触发之前的延迟,在触发之后叫间隔,使用interval设置
    float _interval;             // 时间间隔。

 _scheduler(nullptr)
, _elapsed(-1)
, _runForever(false)
, _useDelay(false)
, _timesExecuted(0)
, _repeat(0)
, _delay(0.0f)
, _interval(0.0f)
, _aborted(false)

设置定时器Timer()

void Timer::setupTimerWithInterval(float seconds, unsigned int repeat, float delay)
{
    _elapsed = -1;  //=-1表示是第一次进入函数,后面的再Update函数中会有初始化操作
    _interval = seconds;
    _delay = delay;
    _useDelay = (_delay > 0.0f) ? true : false;
    _repeat = repeat;
    _runForever = (_repeat == CC_REPEAT_FOREVER) ? true : false;  //CC_REPEAT_FOREVER == -1
    _timesExecuted = 0;
}

void Timer::update(float dt)
{
    if (_elapsed == -1) //表示第一次进入Update方法,进行初始化
    {
        _elapsed = 0;         //已执行时间
        _timesExecuted = 0;   //执行次数
        return;
    }

    // accumulate elapsed time
    _elapsed += dt;  //记录累计度过的时间
    
    // deal with delay
    if (_useDelay)
    {
        if (_elapsed < _delay) // 还没有完成延时
        {
            return;
        }
        _timesExecuted += 1; // important to increment before call trigger
        trigger(_delay);   //      【回调函数】
        _elapsed = _elapsed - _delay; //此时记录的是开始执行之后度过的时间
        _useDelay = false; //延迟结束
        // after delay, the rest time should compare with interval
        if (isExhausted()) //不永远执行并且已经执行完了重复次数
        {    //unschedule timer
            cancel(); 
            return;
        }
    }
    
    // if _interval == 0, should trigger once every frame
    float interval = (_interval > 0) ? _interval : _elapsed; //正常来说interval都是大于零的,如果interval小于零,那就使用度过的时间来代替间隔时间
  //如果度过的时间比间隔要大才会执行
    while ((_elapsed >= interval) && !_aborted) 
    {
        _timesExecuted += 1;  // important to increment before call trigger
        trigger(interval);    //      【回调函数】
        _elapsed -= interval; //记录剩余时间

        if (isExhausted())    //不永远执行并且已经执行完了重复次数
        {
            cancel();
            break;
        }

        if (_elapsed <= 0.f) //间隔时间等于度过的时间
        {
            break;
        }
    }
}

一些成员函数

bool TimerTargetSelector::initWithSelector(Scheduler* scheduler, SEL_SCHEDULE selector, Ref* target, float seconds, unsigned int repeat, float delay)
{
    _scheduler = scheduler;
    _target = target;
    _selector = selector;  //selector没有set方法,通过此方法来初始化
    setupTimerWithInterval(seconds, repeat, delay);
    return true;
}

void TimerTargetSelector::trigger(float dt) //调用回调函数
{
    if (_target && _selector)
    {
        (_target->*_selector)(dt);
    }
}

void TimerTargetSelector::cancel()
{
    _scheduler->unschedule(_selector, _target);
}
class CC_DLL TimerTargetCallback : public Timer
{
public:
   TimerTargetCallback();
   
   // Initializes a timer with a target, a lambda and an interval in seconds, repeat in number of times to repeat, delay in seconds.
   bool initWithCallback(Scheduler* scheduler, const ccSchedulerFunc& callback, void *target, const std::string& key, float seconds, unsigned int repeat, float delay);
   
   const ccSchedulerFunc& getCallback() const { return _callback; }
   const std::string& getKey() const { return _key; }
   
   virtual void trigger(float dt) override;
   virtual void cancel() override;
   
protected:
   void* _target;
   ccSchedulerFunc _callback;
   std::string _key;
};
//初始化
bool TimerTargetCallback::initWithCallback(Scheduler* scheduler, const ccSchedulerFunc& callback, void *target, const std::string& key, float seconds, unsigned int repeat, float delay)
{
   _scheduler = scheduler;
   _target = target;
   _callback = callback;
   _key = key;
   setupTimerWithInterval(seconds, repeat, delay);
   return true;
}
//调用回调函数
void TimerTargetCallback::trigger(float dt)
{
   if (_callback)
   {
       _callback(dt);
   }
}
//
void TimerTargetCallback::cancel()
{
   _scheduler->unschedule(_key, _target);

Scheduler()

经常使用的调度器是:

schedulerUpdate()

scheduler(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay)

scheduleOnce(SEL_SCHEDULE selector, float delay)

变量

pause:启用或暂停此方法。暂停(false),启用(true)

interval:每隔“interval”秒调用一次方法,如果为0,则每一帧都调用,当为0时,建议使用schedulerUpdate。

repeat:触发一次事件后还会触发的次数,为0时触发一次

delay:延迟多少秒,是指在触发之前的延迟,在触发之后叫间隔,使用interval设置

key:用于取消定时器

初始化

typedef struct _listEntry
{
    struct _listEntry   *prev, *next;
    ccSchedulerFunc     callback;
    void                *target;
    int                 priority;
    bool                paused;
    bool                markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick
} tListEntry;

//内置的update定时器
typedef struct _hashUpdateEntry
{
    tListEntry          **list;        // Which list does it belong to ?
    tListEntry          *entry;        // entry in the list
    void                *target;
    ccSchedulerFunc     callback;
    UT_hash_handle      hh;
} tHashUpdateEntry;
 
// 自定义定时器
typedef struct _hashSelectorEntry
{
    ccArray             *timers;
    void                *target;
    int                 timerIndex;
    Timer               *currentTimer;
    bool                currentTimerSalvaged;
    bool                paused;
    UT_hash_handle      hh;
} tHashTimerEntry;
float _timeScale;
    struct _listEntry *_updatesNegList;        // list of priority < 0 三种优先级
    struct _listEntry *_updates0List;            // list priority == 0
    struct _listEntry *_updatesPosList;        // list priority > 0
    struct _hashUpdateEntry *_hashForUpdates; // hash used to fetch quickly the list entries for pause,delete,etc
    std::vector<struct _listEntry *> _updateDeleteVector; // the vector holds list entries that needs to be deleted after update
    // Used for "selectors with interval"
    struct _hashSelectorEntry *_hashForTimers;
    struct _hashSelectorEntry *_currentTarget;
    bool _currentTargetSalvaged;
    // If true unschedule will not remove anything from a hash. Elements will only be marked for deletion.
    bool _updateHashLocked;

//初始化
Scheduler::Scheduler(void)
: _timeScale(1.0f) //播放速度为1.0
, _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
   //预开辟30个空间,且不希望超过30个函数
    _functionsToPerform.reserve(30); 
}

哈希表

#include "base/uthash.h"
typedef struct UT_hash_handle {
   struct UT_hash_table *tbl;
   void *prev;                       /* prev element in app order      */
   void *next;                       /* next element in app order      */
   struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */
   struct UT_hash_handle *hh_next;   /* next hh in bucket order        */
   void *key;                        /* ptr to enclosing struct's key  */
   unsigned keylen;                  /* enclosing struct's key len     */
   unsigned hashv;                   /* result of hash-fcn(key)        */
} UT_hash_handle;

HASH_FIND_PTR(head,findptr,out)
HASH_ADD_PTR(head,ptrfield,add) 
HASH_DEL(head,delptr) 
  
//不同优先级的update定时器的双向链表
typedef struct _listEntry
{
    struct _listEntry   *prev, *next;
    ccSchedulerFunc     callback;
    void                *target;
    int                 priority;
    bool                paused;
    bool                markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick
} tListEntry;

//内置的update定时器
typedef struct _hashUpdateEntry
{
    tListEntry          **list;        // Which list does it belong to ?
    tListEntry          *entry;        // entry in the list
    void                *target;
    ccSchedulerFunc     callback;
    UT_hash_handle      hh;
} tHashUpdateEntry;

//自定义的定时器
typedef struct _hashSelectorEntry
{
    ccArray             *timers; //如下
    void                *target;
    int                 timerIndex;
    Timer               *currentTimer;
    bool                paused;
    UT_hash_handle      hh;
} tHa
typedef struct _ccArray {
	ssize_t num, max;
	Ref** arr;
} ccArray;
void ccArrayAppendObject(ccArray *arr, Ref* object)
{
    CCASSERT(object != nullptr, "Invalid parameter!");
    object->retain();
		arr->arr[arr->num] = object;
		arr->num++;//序号+1
}

构造函数schedule()

//重载版本① 更新选择器 //Ref *target 
void Scheduler::schedule(SEL_SCHEDULE selector, Ref *target, float interval, unsigned int repeat, float delay, bool paused)
{
    CCASSERT(target, "Argument target must be non-nullptr");
   
  //用来记录一个Ref对象加载的所有timer
    tHashTimerEntry *element = nullptr; 
  
  //_hashForTimers是用来记录tHashTimerEntry头结点的指针
  //在_hashForTimers链表中查找与target相等的元素,返回一个element
  //#define HASH_FIND_PTR(head,findptr,out)
    HASH_FIND_PTR(_hashForTimers, &target, element);
    
  //判断有没有找到
    if (! element) 
    {
      //为空则先分配空间
        element = (tHashTimerEntry *)calloc(sizeof(*element), 1);
      //把链表的target指向形参target(把形参的target加入链表)
        element->target = target; 
        
      //再次查找获取链表中的”element“
        HASH_ADD_PTR(_hashForTimers, target, element);
        +
        // Is this the 1st element ? Then set the pause level to all the selectors of this target
          //给获取到的element设置paused的状态
        element->paused = paused; 
    }
  //target已经加入链表了,判断paused的状态是否设定成功
    else 
    {
        CCASSERT(element->paused == paused, "element's paused should be paused.");
    }
    
  //判断定时器列表的状态,如果为空则分配空间
    if (element->timers == nullptr)
    {
        element->timers = ccArrayNew(10);
    }
    else
    {
      //循环定时器结构中的成员
        for (int i = 0; i < element->timers->num; ++i) 
        {
          //获取其中的定时器对象
            TimerTargetSelector *timer = dynamic_cast<TimerTargetSelector*>(element->timers->arr[i]);
            
          //如果定义过定时器,则重新设置interval, repeat, delay
            if (timer && !timer->isExhausted() && selector == timer->getSelector())
            {
                CCLOG("CCScheduler#schedule. Reiniting timer with interval %.4f, repeat %u, delay %.4f", interval, repeat, delay);
                timer->setupTimerWithInterval(interval, repeat, delay);
                return;
            }
        }
      //检查ccArray的内存,确定可以再添加一个timers
        ccArrayEnsureExtraCapacity(element->timers, 1); 
    }
    
  //创建了一个新的TimerTargetSelector对象(timer),用上面处理过的实参对其初始化,并且加到定时器列表(timers)中
    TimerTargetSelector *timer = new (std::nothrow) TimerTargetSelector();
    timer->initWithSelector(this, selector, target, interval, repeat, delay);
    ccArrayAppendObject(element->timers, timer);//object->retain();
    timer->release();
}
//重载版本②//使用回调函数callback 多了 形参key和repeat //自定义选择器 void *target
void Scheduler::schedule(const ccSchedulerFunc& callback, void *target, float interval, unsigned int repeat, float delay, bool paused, const std::string& key)
{
    CCASSERT(target, "Argument target must be non-nullptr");
    CCASSERT(!key.empty(), "key should not be empty!");

    tHashTimerEntry *element = nullptr;
    HASH_FIND_PTR(_hashForTimers, &target, element);

    if (! element)
    {
        element = (tHashTimerEntry *)calloc(sizeof(*element), 1);
        element->target = target;

        HASH_ADD_PTR(_hashForTimers, target, element);

        // Is this the 1st element ? Then set the pause level to all the selectors of this target
        element->paused = paused;
    }
    else
    {
        CCASSERT(element->paused == paused, "element's paused should be paused!");
    }

    if (element->timers == nullptr)
    {
        element->timers = ccArrayNew(10);
    }
    else 
    {
        for (int i = 0; i < element->timers->num; ++i)
        {
            TimerTargetCallback *timer = dynamic_cast<TimerTargetCallback*>(element->timers->arr[i]);

            if (timer && !timer->isExhausted() && key == timer->getKey())
            {
                CCLOG("CCScheduler#schedule. Reiniting timer with interval %.4f, repeat %u, delay %.4f", interval, repeat, delay);
                timer->setupTimerWithInterval(interval, repeat, delay);
                return;
            }
        }
        ccArrayEnsureExtraCapacity(element->timers, 1);
    }

    TimerTargetCallback *timer = new (std::nothrow) TimerTargetCallback();
    timer->initWithCallback(this, callback, target, key, interval, repeat, delay);
    ccArrayAppendObject(element->timers, timer);
    timer->release();
}
//重载版本③ //永远执行   repeat = CC_REPEAT_FOREVER
void Scheduler::schedule(const ccSchedulerFunc& callback, void *target, float interval, bool paused, const std::string& key)
{
    this->schedule(callback, target, interval, CC_REPEAT_FOREVER, 0.0f, paused, key);
}
//重载版本④ //永远执行  repeat = CC_REPEAT_FOREVER
void Scheduler::schedule(SEL_SCHEDULE selector, Ref *target, float interval, bool paused)
{
    this->schedule(selector, target, interval, CC_REPEAT_FOREVER, 0.0f, paused);
}

开启定时器Update()

/*
void Node::scheduleUpdate()
{
    scheduleUpdateWithPriority(0);
}
*/
//每帧执行一次,默认优先级为0,优先级越小越先执行
void Node::scheduleUpdateWithPriority(int priority)
{
    _scheduler->scheduleUpdate(this, priority, !_running);
}
//默认优先级为0,在所有自定义方法之前执行
template <class T>
    void scheduleUpdate(T *target, int priority, bool paused)
    {
        this->schedulePerFrame([target](float dt){
            target->update(dt);
        }, target, priority, paused);
    }
void Scheduler::schedulePerFrame(const ccSchedulerFunc& callback, void *target, int priority, bool paused)
{
  	//定义一个hash链表对象
    tHashUpdateEntry *hashElement = nullptr;
  	//查找target,结果通过hashElement返回
    HASH_FIND_PTR(_hashForUpdates, &target, hashElement);
  	//如果找到了
    if (hashElement)
    {
        // change priority: should unschedule it first
      //检查优先级是否已经被修改,如果还未修改,先取消修改的计划;
      //如果已经被修改,则提示不要重复执行修改操作
        if (hashElement->entry->priority != priority)
        {
            unscheduleUpdate(target);
        }
        else
        {
            // don't add it again
            CCLOG("warning: don't update it again");
            return;
        }
    }

    // most of the updates are going to be 0, that's way there
    // is an special list for updates with priority 0
 		//然后将其加入到对应优先级的链表中
    if (priority == 0)
    {
        appendIn(&_updates0List, callback, target, paused);//如下
    }
    else if (priority < 0)
    {
        priorityIn(&_updatesNegList, callback, target, priority, paused);//如下
    }
    else
    {
        // priority > 0
        priorityIn(&_updatesPosList, callback, target, priority, paused);
    }
}
//appendIn()用于添加默认优先级的
void Scheduler::appendIn(_listEntry **list, const ccSchedulerFunc& callback, void *target, bool paused)
{
  //新建优先级更新链表
    tListEntry *listElement = new (std::nothrow) tListEntry();

    listElement->callback = callback;
    listElement->target = target;
    listElement->paused = paused;
    listElement->priority = 0;
    listElement->markedForDeletion = false;

  //把listElement加到优先级为0的list中
    DL_APPEND(*list, listElement);

    // update hash entry for quicker access
  //创建一个hash链表指针对象
    tHashUpdateEntry *hashElement = (tHashUpdateEntry *)calloc(sizeof(*hashElement), 1);
    hashElement->target = target;
    hashElement->list = list;
    hashElement->entry = listElement;
    memset(&hashElement->hh, 0, sizeof(hashElement->hh));
 //把hashElement添加到_hashForUpdates中
    HASH_ADD_PTR(_hashForUpdates, target, hashElement);
}
//priorityIn()用于添加指定优先级
void Scheduler::priorityIn(tListEntry **list, const ccSchedulerFunc& callback, void *target, int priority, bool paused)
{
  //同上
    tListEntry *listElement = new (std::nothrow) tListEntry();

    listElement->callback = callback;
    listElement->target = target;
    listElement->priority = priority;
    listElement->paused = paused;
    listElement->next = listElement->prev = nullptr;
    listElement->markedForDeletion = false;

    //判断优先级<0的链表是不是空的
    if (! *list)
    {
      //是空的直接添加
        DL_APPEND(*list, listElement);
    }
    else
    {
      //设置一个add表示还未添加完成
        bool added = false;

        for (tListEntry *element = *list; element; element = element->next)
        {
          //如果添加的元素的优先级 < 被循环到的元素的优先级,
          //说明插入的元素优先级更高,则会被插入到循环的这个元素之前
            if (priority < element->priority)
            {
                if (element == *list)
                {
                    DL_PREPEND(*list, listElement);
                }
                else
                {
                  //tListEntry *element = *list的备选路径
                    listElement->next = element;
                    listElement->prev = element->prev;

                    element->prev->next = listElement;
                    element->prev = listElement;
                }
							//添加完成了     
                added = true;
                break;
            }
        }

        // Not added? priority has the higher value. Append it.
      //是否添加完成(未完成说明插入的元素在链表中的优先级最低,插入到链表最后) 
      if (! added)
        {
            DL_APPEND(*list, listElement);
        }
    }

    // update hash entry for quick access
  //同上
    tHashUpdateEntry *hashElement = (tHashUpdateEntry *)calloc(sizeof(*hashElement), 1);
    hashElement->target = target;
    hashElement->list = list;
    hashElement->entry = listElement;
    memset(&hashElement->hh, 0, sizeof(hashElement->hh));
    HASH_ADD_PTR(_hashForUpdates, target, hashElement);
}

析构函数~Update()

void Scheduler::unschedule(const std::string &key, void *target)
{
    // explicit handle nil arguments when removing an object
    if (target == nullptr || key.empty())
    {
        return;
    }

    //CCASSERT(target);
    //CCASSERT(selector);

    tHashTimerEntry *element = nullptr;
    HASH_FIND_PTR(_hashForTimers, &target, element);

    if (element)
    {
        for (int i = 0; i < element->timers->num; ++i)
        {
            TimerTargetCallback *timer = dynamic_cast<TimerTargetCallback*>(element->timers->arr[i]);
						//找到要移除的timer
            if (timer && key == timer->getKey())
            {
                if (timer == element->currentTimer && (! timer->isAborted()))
                {
                    timer->retain();//+1
                    timer->setAborted();//设置延迟释放,下面还要继续访问
                }
								//在这里调用CC_SAFE_RELEASE -1
                ccArrayRemoveObjectAtIndex(element->timers, i, true);

                // update timerIndex in case we are in tick:, looping over the actions
            	  //个数-1
                if (element->timerIndex >= i)
                {
                    element->timerIndex--;
                }
								//timers里面没有timer了
                if (element->timers->num == 0)
                {
                  	//标记需要被删除,在刷新函数中执行移除操作
                    if (_currentTarget == element)
                    {
                        _currentTargetSalvaged = true;
                    }
                    else
                    {
                      //链表中移除  移除之后是安全的了,回到Scheduler::update()中再release()释放
                        removeHashElement(element);
                    }
                }

                return;
            }
        }
    }
}

Update()

void Scheduler::update(float dt)
{
  //状态锁
    _updateHashLocked = true;
	//调整时间速率
    if (_timeScale != 1.0f)
    {
        dt *= _timeScale;
    }

    //
    // Selector callbacks
    //

    // Iterate over all the Updates' selectors
    tListEntry *entry, *tmp;

    // updates with priority < 0
  	//先执行优先级高的 priority < 0
    DL_FOREACH_SAFE(_updatesNegList, entry, tmp)
    {
      //对没有暂停的和没有被标记需要删除的执行回调函数
        if ((! entry->paused) && (! entry->markedForDeletion))
        {
            entry->callback(dt);
        }
    }

    // updates with priority == 0
    DL_FOREACH_SAFE(_updates0List, entry, tmp)
    {
        if ((! entry->paused) && (! entry->markedForDeletion))
        {
            entry->callback(dt);
        }
    }

    // updates with priority > 0
    DL_FOREACH_SAFE(_updatesPosList, entry, tmp)
    {
        if ((! entry->paused) && (! entry->markedForDeletion))
        {
            entry->callback(dt);
        }
    }

    // Iterate over all the custom selectors
  	//遍历自定义的定时器
    for (tHashTimerEntry *elt = _hashForTimers; elt != nullptr; )
    {
        _currentTarget = elt; //标记执行到了那个target对象
        _currentTargetSalvaged = false; //设置定时器为可用状态

        if (! _currentTarget->paused)
        {
            // The 'timers' array may change while inside this loop
          	//遍历当前对象的所有定时器
            for (elt->timerIndex = 0; elt->timerIndex < elt->timers->num; ++(elt->timerIndex))
            {
              //标记执行到了那个timer对象
                elt->currentTimer = (Timer*)(elt->timers->arr[elt->timerIndex]);
              //如果已经被弃用  
              CCASSERT( !elt->currentTimer->isAborted(),
                    "An aborted timer should not be updated" );
								//
                elt->currentTimer->update(dt);//执行定时器的update()!! 在这里执行定时器的回调函数
								//如果被弃用了就释放它 执行了上面一条语句之后,已经被从链表中移除了,这时候释放才是安全的
                if (elt->currentTimer->isAborted())
                {
                    // The currentTimer told the remove itself. To prevent the timer from
                    // accidentally deallocating itself before finishing its step, we retained
                    // it. Now that step is done, it's safe to release it.
                    elt->currentTimer->release();
                }
								//当前执行到的timer对象置空
                elt->currentTimer = nullptr;  
            }
        }

        // elt, at this moment, is still valid
        // so it is safe to ask this here (issue #490)
      	//链表继续往后访问
        elt = (tHashTimerEntry *)elt->hh.next;

        // only delete currentTarget if no actions were scheduled during the cycle (issue #481)
      	//如果被标记弃用并且里面没有timer了,就移除它(定时器已经执行完成了)
        if (_currentTargetSalvaged && _currentTarget->timers->num == 0)
        {
            removeHashElement(_currentTarget);
        }
    }
 
    // delete all updates that are removed in update
  	//移除所有标记为要删除的update定时器元素
    for (auto &e : _updateDeleteVector)
        delete e;
		//清空待删除数组
    _updateDeleteVector.clear();
		
  	//移除状态锁
    _updateHashLocked = false;
  	//执行到的target对象置空
    _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
    //
    // Functions allocated from another thread
    //

    // 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 = std::move(_functionsToPerform);
        _performMutex.unlock();
        
        for (const auto &function : temp) {
            function();
        }
    }
}

removeUpdateFromHash()

void Scheduler::unscheduleUpdate(void *target)
{
    if (target == nullptr)
    {
        return;
    }

    tHashUpdateEntry *element = nullptr;
    HASH_FIND_PTR(_hashForUpdates, &target, element);
    if (element)
        this->removeUpdateFromHash(element->entry);										//   
}
void Scheduler::removeUpdateFromHash(struct _listEntry *entry)
{
    tHashUpdateEntry *element = nullptr;

    HASH_FIND_PTR(_hashForUpdates, &entry->target, element);
    if (element)
    {
        // list entry
        DL_DELETE(*element->list, element->entry);
        if (!_updateHashLocked)
            CC_SAFE_DELETE(element->entry);
        else
        {
            element->entry->markedForDeletion = true;
            _updateDeleteVector.push_back(element->entry);									//   
        }

        // hash entry
        HASH_DEL(_hashForUpdates, element);
        free(element);
    }
}

一些成员函数

//通过key和target来判断当前对象是否在定时器中
bool isScheduled(const std::string& key, const void *target) const;
//判断条件不同
bool isScheduled(SEL_SCHEDULE selector, const Ref *target) const;
//恢复一个对象的定时器
void resumeTarget(void *target);
//查询一个对象的定时器装状态
bool isTargetPaused(void *target);
//暂停所有的定时器
std::set<void*> pauseAllTargets();
//恢复所有的定时器
void resumeTargets(const std::set<void*>& targetsToResume);

补充

1、为什么使用colloc不使用malloc?
究其根本是malloc和colloc区别的原因,
使用
malloc:(type*)malloc(size) 分配一个size大小的内存空间返回type类型的指针指向内存的首地址
colloc:(type*)colloc(n,size) 分配n个size大小的连续内存空间返回type类型的指针指向第一个内存的首地址
最大的区别是:malloc只分配内存空间不做初始化,原先内存中的数据依然存在,可能会造成数据错误;colloc分配空间后进行初始化,将分配的空间都初始化为0,避免了数据错误。

2、std::move
std::string str = "Hello";
std::vector<std::string> v;

v.push_back(str); 
std::cout<<v[0]; //输出hello 
std::cout<<str; //输出hello

v.push_back(std::move(str));
std::cout<<v[0]; //输出hello 
std::cout<<v[1]; //输出hello
std::cout<<str; //输出为空


posted @ 2019-07-26 22:28  软不隆咚的二更  阅读(111)  评论(0编辑  收藏  举报