1、分析下update类型,即每帧都调用的定时器,如何实现:
//CCScheduler中的成员变量 struct _listEntry *m_pUpdates0List; // list priority == 0 -->>存放update类型定时器的结构 // A list double-linked list used for "updates with priority" typedef struct _listEntry { struct _listEntry *prev,*next; CCObject *target; // not retained (retained by hashUpdateEntry) int priority; bool paused; bool markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick } tListEntry;
2、添加update类型的定时器 /** Schedules the 'update' selector for a given target with a given priority. The 'update' selector will be called every frame. The lower the priority,the earlier it is called. @since v0.99.3 @lua NA */ void scheduleUpdateForTarget(CCObject *pTarget,int nPriority,bool bPaused); -->> void CCScheduler::scheduleUpdateForTarget(CCObject *pTarget,bool bPaused) { //先判断是否已经加入 tHashUpdateEntry *pHashElement = NULL; HASH_FIND_INT(m_pHashForUpdates,&pTarget,pHashElement); if (pHashElement) { #if COCOS2D_DEBUG >= 1 CCAssert(pHashElement->entry->markedForDeletion,""); #endif // TODO: check if priority has changed! pHashElement->entry->paused = bPaused; pHashElement->entry->markedForDeletion = false; return; } //根据优先级加入到不同的链表中 // most of the updates are going to be 0,that's way there // is an special list for updates with priority 0 if (nPriority == 0) { appendIn(&m_pUpdates0List,pTarget,bPaused); } else if (nPriority < 0) { priorityIn(&m_pUpdatesNegList,nPriority,bPaused); } else { // priority > 0 priorityIn(&m_pUpdatesPosList,bPaused); } } -->>分析下appendIn(&m_pUpdates0List,bPaused)这个,其他连个类似,只不过 加入了优先级的概念,需要根据优先级确定插入位置,但是都为加入到快速查找哈希链表中, 而且同样会retain。 void CCScheduler::appendIn(_listEntry **ppList,CCObject *pTarget,bool bPaused) { //分配tListEntry tListEntry *pListElement = (tListEntry *)malloc(sizeof(*pListElement)); pListElement->target = pTarget; pListElement->paused = bPaused; pListElement->markedForDeletion = false; //添加进列表 DL_APPEND(*ppList,pListElement); //添加到快速查找哈希链表中 // update hash entry for quicker access tHashUpdateEntry *pHashElement = (tHashUpdateEntry *)calloc(sizeof(*pHashElement),1); pHashElement->target = pTarget; pTarget->retain(); //有一次retain对象的操作,会影响对象的释放 pHashElement->list = ppList; pHashElement->entry = pListElement; HASH_ADD_INT(m_pHashForUpdates,target,pHashElement); } 3、移除update类型的定时器 /** Unschedules the update selector for a given target @since v0.99.3 @lua NA */ void unscheduleUpdateForTarget(const CCObject *pTarget); -->> void CCScheduler::unscheduleUpdateForTarget(const CCObject *pTarget) { if (pTarget == NULL) { return; } //如果哈希表中有 tHashUpdateEntry *pElement = NULL; HASH_FIND_INT(m_pHashForUpdates,pElement); if (pElement) { if (m_bUpdateHashLocked) { pElement->entry->markedForDeletion = true; //标记为移除 } else { this->removeUpdateFromHash(pElement->entry);//真正的移除 } } } -->> void CCScheduler::removeUpdateFromHash(struct _listEntry *entry) { tHashUpdateEntry *element = NULL; HASH_FIND_INT(m_pHashForUpdates,&entry->target,element); if (element) { // list entry,从链表移除 DL_DELETE(*element->list,element->entry); free(element->entry); // hash entry,从哈希表移除 CCObject* pTarget = element->target; HASH_DEL(m_pHashForUpdates,element); free(element); // target#release should be the last one to prevent // a possible double-free. eg: If the [target dealloc] might want to remove it itself from there pTarget->release(); //对对象执行一次release操作 } }