Potential problem in cocos2d::Scheduler

I noticed cocos2d::Schedule has some methods to use void* and some to use cocos2d::Ref* as target type when I was making SpeedCC, such as Scheduler::unscheduleAllForTarget(void *target). This design will cause below potential problem.

class MyClassA
{
public: virtual ~MyClassA() {}
int a;	
};

class MyClassB : public MyClassA, public cocos2d::Ref
{
public:
	void start()
	{
		auto sch = cocos2d::Director::getInstance()->getScheduler();
		sch->schedule(CC_SCHEDULE_SELECTOR(MyClassB::onSchedule),this,3,false);
	}

	void stop()
	{
		auto sch = cocos2d::Director::getInstance()->getScheduler();
		sch->unschedule(CC_SCHEDULE_SELECTOR(MyClassB::onSchedule),this); // line A: it CAN stop schedule as expect.
		// sch->unscheduleAllForTarget(this); // line B: it CAN NOT stop schedule, and no crash immediately as well.
		// sch->unscheduleAllForTarget(static_cast<cocos2d::Ref*>(this)); // line C: it CAN stop schedule as expect.
	}

	void onSchedule(float fDelta)
	{
		CCLOG("onSchedule()");
	}
};

I have to always use static_cast<cocos2d::Ref*> for target in schedule to prevent this potential issue, because I don’t want to confirm the type of target every time when using cocos2d::schedule methods, it looks ridiculous, but maybe some reasons behind it, so my question is:

What’s reason did engine team consider to design target in void* instead of cocos2d::Ref*? And what’s reason for some methods to use void* and some to use cocos2d::Ref*?

@zhangxm @slackmoehrle

cocos2d employs the third-party library uthash to implement hash table in cocos2d::Scheduler, in which the routines beneath accept void* as arguments, e.g. HASH_FIND_PTR. Hence my wild guess is the author of cocos2d::Scheduler was just trying to fit the API requirement. And cocos2dx has adopted the scheduler methods to objects not inheriting from cocos2d::Ref, such as HttpClient.
Referring to your problem, the reason of line B not working is due to the multiple inheritance of MyClassB, the C++ compiler will automatically assign the this pointer to the first candidate in the list of base classes, which is MyClassA in your case. If you switch the inheritance of cocos2d::Ref in front of MyClassA, the issue should be gone.

P.S. As always, like many other libraries, cocos2dx is using an outdated version of uthash.

@ichinfungi Thanks for your reply. Yes, you are right.

I know what’s reason cause my problem, but I don’t know why schedule is such design in which update and timer mixed in one class and causes parameters confused.

I will pass this along to the engine team via a GitHub issue

1 Like