不管是学习还是工作,最怕的就是停止思考,做cocos已然很多年了,api随手捏来,但是只是停留在使用的层面,从来没有深究细节,so,做了很多年感觉自己还是一个菜逼。
代码解析:
tHashTimerEntry *element = nullptr; HASH_FIND_PTR(_hashForTimers, &target, element);//ps: _hashForTimers 是存储element(timerhandler)的hash表。
//ps: 通过传入的&target来查找是否存在这个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 && key == timer->getKey())//ps:如果找到这个key的timer,更新这个timer的间隔信息 { CCLOG("CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f", timer->getInterval(), interval); timer->setInterval(interval); return; } } ccArrayEnsureExtraCapacity(element->timers, 1);//ps: 如果没有相同key的timer,则需要将timer的长度+1
} TimerTargetCallback *timer = new (std::nothrow) TimerTargetCallback(); timer->initWithCallback(this, callback, target, key, interval, repeat, delay); ccArrayAppendObject(element->timers, timer); timer->release();
scheduer 本质上是一个timer管理中心,每一个target启动定时器的时候,scheduer会检查队列中是否存在这个target对应的timerhandler,如果已经存在,则找到这个handler,如果没有创建实例,加到队列中,所以每个target共享timer的名字。(ps:给scheduer取名字的时候不要太担心会重复,只要保重同一个对象实例中不重复就行)