zoukankan      html  css  js  c++  java
  • 从零开始の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; //输出为空
    
    
    
  • 相关阅读:
    ASP.NET MVC案例——————拦截器
    Windows Azure Virtual Network (10) 使用Azure Access Control List(ACL)设置客户端访问权限
    Windows Azure Storage (20) 使用Azure File实现共享文件夹
    Windows Azure HandBook (5) Azure混合云解决方案
    Windows Azure Service Bus (6) 中继(Relay On) 使用VS2013开发Service Bus Relay On
    Azure PowerShell (9) 使用PowerShell导出订阅下所有的Azure VM的Public IP和Private IP
    Windows Azure Service Bus (5) 主题(Topic) 使用VS2013开发Service Bus Topic
    Azure China (9) 在Azure China配置CDN服务
    Windows Azure Storage (19) 再谈Azure Block Blob和Page Blob
    Windows Azure HandBook (4) 分析Windows Azure如何处理Session
  • 原文地址:https://www.cnblogs.com/sakuraneo/p/11992059.html
Copyright © 2011-2022 走看看