2012-02-01 16:45:23 +08:00
/****************************************************************************
Copyright ( c ) 2008 - 2010 Ricardo Quesada
2014-01-07 11:25:07 +08:00
Copyright ( c ) 2010 - 2012 cocos2d - x . org
2012-02-01 16:45:23 +08:00
Copyright ( c ) 2011 Zynga Inc .
2016-08-05 09:42:15 +08:00
Copyright ( c ) 2013 - 2016 Chukong Technologies Inc .
2012-02-01 16:45:23 +08:00
http : //www.cocos2d-x.org
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-04-30 08:37:36 +08:00
# include "base/CCScheduler.h"
# include "base/ccMacros.h"
# include "base/CCDirector.h"
2014-05-17 05:36:00 +08:00
# include "base/utlist.h"
# include "base/ccCArray.h"
# include "base/CCScriptSupport.h"
2012-02-02 15:58:10 +08:00
2012-04-18 18:43:45 +08:00
NS_CC_BEGIN
2012-02-01 16:45:23 +08:00
// data structures
// A list double-linked list used for "updates with priority"
typedef struct _listEntry
{
2012-12-10 13:48:27 +08:00
struct _listEntry * prev , * next ;
2014-02-20 10:53:49 +08:00
ccSchedulerFunc callback ;
2014-03-01 13:30:20 +08:00
void * target ;
2012-12-10 13:48:27 +08:00
int priority ;
2012-04-19 14:35:52 +08:00
bool paused ;
bool markedForDeletion ; // selector will no longer be called and entry will be removed at end of the next tick
2012-02-01 16:45:23 +08:00
} tListEntry ;
typedef struct _hashUpdateEntry
{
2012-12-10 13:48:27 +08:00
tListEntry * * list ; // Which list does it belong to ?
tListEntry * entry ; // entry in the list
2014-02-20 14:11:47 +08:00
void * target ;
2014-02-20 10:53:49 +08:00
ccSchedulerFunc callback ;
2012-12-10 13:48:27 +08:00
UT_hash_handle hh ;
2012-02-01 16:45:23 +08:00
} tHashUpdateEntry ;
// Hash Element used for "selectors with interval"
typedef struct _hashSelectorEntry
{
2012-12-10 13:48:27 +08:00
ccArray * timers ;
2014-02-20 14:11:47 +08:00
void * target ;
2014-02-20 10:53:49 +08:00
int timerIndex ;
Timer * currentTimer ;
2012-12-10 13:48:27 +08:00
bool currentTimerSalvaged ;
bool paused ;
UT_hash_handle hh ;
2012-11-14 18:05:15 +08:00
} tHashTimerEntry ;
2012-02-01 16:45:23 +08:00
2013-06-20 14:13:12 +08:00
// implementation Timer
2012-02-01 16:45:23 +08:00
2013-06-20 14:13:12 +08:00
Timer : : Timer ( )
2014-03-03 17:51:27 +08:00
: _scheduler ( nullptr )
, _elapsed ( - 1 )
2013-06-15 14:03:30 +08:00
, _runForever ( false )
, _useDelay ( false )
, _timesExecuted ( 0 )
, _repeat ( 0 )
, _delay ( 0.0f )
, _interval ( 0.0f )
2012-02-02 15:58:10 +08:00
{
}
2014-03-01 13:30:20 +08:00
void Timer : : setupTimerWithInterval ( float seconds , unsigned int repeat , float delay )
2012-02-02 15:58:10 +08:00
{
2014-03-01 13:30:20 +08:00
_elapsed = - 1 ;
_interval = seconds ;
_delay = delay ;
_useDelay = ( _delay > 0.0f ) ? true : false ;
_repeat = repeat ;
2014-10-04 00:38:36 +08:00
_runForever = ( _repeat = = CC_REPEAT_FOREVER ) ? true : false ;
2012-02-01 16:45:23 +08:00
}
2013-06-20 14:13:12 +08:00
void Timer : : update ( float dt )
2012-02-01 16:45:23 +08:00
{
2013-06-15 14:03:30 +08:00
if ( _elapsed = = - 1 )
2012-04-19 14:35:52 +08:00
{
2013-06-15 14:03:30 +08:00
_elapsed = 0 ;
_timesExecuted = 0 ;
2015-08-13 12:55:07 +08:00
return ;
2012-04-19 14:35:52 +08:00
}
2015-08-13 12:55:07 +08:00
// accumulate elapsed time
_elapsed + = dt ;
// deal with delay
if ( _useDelay )
2012-04-19 14:35:52 +08:00
{
2015-08-13 12:55:07 +08:00
if ( _elapsed < _delay )
{
return ;
}
trigger ( _delay ) ;
_elapsed = _elapsed - _delay ;
_timesExecuted + = 1 ;
_useDelay = false ;
// after delay, the rest time should compare with interval
if ( ! _runForever & & _timesExecuted > _repeat )
{ //unschedule timer
cancel ( ) ;
return ;
2012-04-19 14:35:52 +08:00
}
}
2015-08-13 12:55:07 +08:00
// if _interval == 0, should trigger once every frame
float interval = ( _interval > 0 ) ? _interval : _elapsed ;
while ( _elapsed > = interval )
{
trigger ( interval ) ;
_elapsed - = interval ;
2015-08-14 15:05:25 +08:00
_timesExecuted + = 1 ;
2015-08-26 23:41:48 +08:00
if ( ! _runForever & & _timesExecuted > _repeat )
2015-08-14 15:05:25 +08:00
{
2015-08-26 23:41:48 +08:00
cancel ( ) ;
2015-08-14 15:05:25 +08:00
break ;
}
2012-02-01 16:45:23 +08:00
2015-08-26 23:41:48 +08:00
if ( _elapsed < = 0.f )
2015-08-13 12:55:07 +08:00
{
break ;
}
}
}
2014-03-01 13:30:20 +08:00
// TimerTargetSelector
TimerTargetSelector : : TimerTargetSelector ( )
: _target ( nullptr )
, _selector ( nullptr )
{
}
2014-03-03 17:51:27 +08:00
bool TimerTargetSelector : : initWithSelector ( Scheduler * scheduler , SEL_SCHEDULE selector , Ref * target , float seconds , unsigned int repeat , float delay )
2014-03-01 13:30:20 +08:00
{
2014-03-03 17:51:27 +08:00
_scheduler = scheduler ;
2014-03-01 13:30:20 +08:00
_target = target ;
_selector = selector ;
setupTimerWithInterval ( seconds , repeat , delay ) ;
return true ;
}
2015-08-13 12:55:07 +08:00
void TimerTargetSelector : : trigger ( float dt )
2014-03-01 13:30:20 +08:00
{
if ( _target & & _selector )
{
2015-08-13 12:55:07 +08:00
( _target - > * _selector ) ( dt ) ;
2014-03-01 13:30:20 +08:00
}
}
void TimerTargetSelector : : cancel ( )
{
2014-03-03 17:51:27 +08:00
_scheduler - > unschedule ( _selector , _target ) ;
2014-03-01 13:30:20 +08:00
}
// TimerTargetCallback
TimerTargetCallback : : TimerTargetCallback ( )
: _target ( nullptr )
, _callback ( nullptr )
{
}
2014-03-03 17:51:27 +08:00
bool TimerTargetCallback : : initWithCallback ( Scheduler * scheduler , const ccSchedulerFunc & callback , void * target , const std : : string & key , float seconds , unsigned int repeat , float delay )
2014-03-01 13:30:20 +08:00
{
2014-03-03 17:51:27 +08:00
_scheduler = scheduler ;
2014-03-01 13:30:20 +08:00
_target = target ;
_callback = callback ;
_key = key ;
setupTimerWithInterval ( seconds , repeat , delay ) ;
return true ;
}
2015-08-13 12:55:07 +08:00
void TimerTargetCallback : : trigger ( float dt )
2014-03-01 13:30:20 +08:00
{
if ( _callback )
{
2015-08-13 12:55:07 +08:00
_callback ( dt ) ;
2014-03-01 13:30:20 +08:00
}
}
void TimerTargetCallback : : cancel ( )
{
2014-03-03 17:51:27 +08:00
_scheduler - > unschedule ( _key , _target ) ;
2014-03-01 13:30:20 +08:00
}
# if CC_ENABLE_SCRIPT_BINDING
// TimerScriptHandler
bool TimerScriptHandler : : initWithScriptHandler ( int handler , float seconds )
{
_scriptHandler = handler ;
_elapsed = - 1 ;
_interval = seconds ;
return true ;
}
2015-08-13 12:55:07 +08:00
void TimerScriptHandler : : trigger ( float dt )
2014-03-01 13:30:20 +08:00
{
if ( 0 ! = _scriptHandler )
{
2015-08-13 12:55:07 +08:00
SchedulerScriptData data ( _scriptHandler , dt ) ;
2014-03-01 13:30:20 +08:00
ScriptEvent event ( kScheduleEvent , & data ) ;
ScriptEngineManager : : getInstance ( ) - > getScriptEngine ( ) - > sendEvent ( & event ) ;
}
}
void TimerScriptHandler : : cancel ( )
{
2014-03-05 09:51:57 +08:00
2014-03-01 13:30:20 +08:00
}
# endif
2013-06-20 14:13:12 +08:00
// implementation of Scheduler
2012-02-01 16:45:23 +08:00
2013-07-25 21:04:32 +08:00
// Priority level reserved for system services.
const int Scheduler : : PRIORITY_SYSTEM = INT_MIN ;
// Minimum priority level for user scheduling.
const int Scheduler : : PRIORITY_NON_SYSTEM_MIN = PRIORITY_SYSTEM + 1 ;
2013-06-20 14:13:12 +08:00
Scheduler : : Scheduler ( void )
2013-06-15 14:03:30 +08:00
: _timeScale ( 1.0f )
2013-11-16 21:08:00 +08:00
, _updatesNegList ( nullptr )
, _updates0List ( nullptr )
, _updatesPosList ( nullptr )
, _hashForUpdates ( nullptr )
, _hashForTimers ( nullptr )
, _currentTarget ( nullptr )
2013-06-15 14:03:30 +08:00
, _currentTargetSalvaged ( false )
, _updateHashLocked ( false )
2014-02-20 16:40:46 +08:00
# if CC_ENABLE_SCRIPT_BINDING
2013-12-07 14:25:24 +08:00
, _scriptHandlerEntries ( 20 )
2014-02-20 16:40:46 +08:00
# endif
2012-02-01 16:45:23 +08:00
{
2013-11-27 08:58:14 +08:00
// I don't expect to have more than 30 functions to all per frame
_functionsToPerform . reserve ( 30 ) ;
2012-02-01 16:45:23 +08:00
}
2013-06-20 14:13:12 +08:00
Scheduler : : ~ Scheduler ( void )
2012-02-01 16:45:23 +08:00
{
2012-11-14 18:05:15 +08:00
unscheduleAll ( ) ;
2012-02-01 16:45:23 +08:00
}
2013-07-18 07:56:19 +08:00
void Scheduler : : removeHashElement ( _hashSelectorEntry * element )
2012-02-01 16:45:23 +08:00
{
2013-07-18 07:56:19 +08:00
ccArrayFree ( element - > timers ) ;
HASH_DEL ( _hashForTimers , element ) ;
free ( element ) ;
2012-02-01 16:45:23 +08:00
}
2014-03-03 11:00:30 +08:00
void Scheduler : : schedule ( const ccSchedulerFunc & callback , void * target , float interval , bool paused , const std : : string & key )
2012-03-14 14:55:17 +08:00
{
2014-10-04 00:38:36 +08:00
this - > schedule ( callback , target , interval , CC_REPEAT_FOREVER , 0.0f , paused , key ) ;
2012-03-14 14:55:17 +08:00
}
2014-03-03 11:00:30 +08:00
void Scheduler : : schedule ( const ccSchedulerFunc & callback , void * target , float interval , unsigned int repeat , float delay , bool paused , const std : : string & key )
2012-02-01 16:45:23 +08:00
{
2013-11-16 21:08:00 +08:00
CCASSERT ( target , " Argument target must be non-nullptr " ) ;
2014-03-01 13:30:20 +08:00
CCASSERT ( ! key . empty ( ) , " key should not be empty! " ) ;
2012-04-19 14:35:52 +08:00
2013-11-16 21:08:00 +08:00
tHashTimerEntry * element = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForTimers , & target , element ) ;
2012-04-19 14:35:52 +08:00
2013-07-18 07:56:19 +08:00
if ( ! element )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
element = ( tHashTimerEntry * ) calloc ( sizeof ( * element ) , 1 ) ;
element - > target = target ;
2014-02-20 14:11:47 +08:00
2013-11-11 12:47:48 +08:00
HASH_ADD_PTR ( _hashForTimers , target , element ) ;
2012-04-19 14:35:52 +08:00
// Is this the 1st element ? Then set the pause level to all the selectors of this target
2013-07-18 07:56:19 +08:00
element - > paused = paused ;
2012-04-19 14:35:52 +08:00
}
else
{
2015-07-14 15:28:36 +08:00
CCASSERT ( element - > paused = = paused , " element's paused should be paused! " ) ;
2012-04-19 14:35:52 +08:00
}
2013-11-16 21:08:00 +08:00
if ( element - > timers = = nullptr )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
element - > timers = ccArrayNew ( 10 ) ;
2012-04-19 14:35:52 +08:00
}
else
{
2013-09-08 11:26:38 +08:00
for ( int i = 0 ; i < element - > timers - > num ; + + i )
2012-04-19 14:35:52 +08:00
{
2015-01-27 17:29:12 +08:00
TimerTargetCallback * timer = dynamic_cast < TimerTargetCallback * > ( element - > timers - > arr [ i ] ) ;
2012-04-19 14:35:52 +08:00
2015-01-27 17:29:12 +08:00
if ( timer & & key = = timer - > getKey ( ) )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
CCLOG ( " CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f " , timer - > getInterval ( ) , interval ) ;
timer - > setInterval ( interval ) ;
2012-04-19 14:35:52 +08:00
return ;
}
}
2013-07-18 07:56:19 +08:00
ccArrayEnsureExtraCapacity ( element - > timers , 1 ) ;
2012-04-19 14:35:52 +08:00
}
2014-08-28 07:31:57 +08:00
TimerTargetCallback * timer = new ( std : : nothrow ) TimerTargetCallback ( ) ;
2014-03-03 17:51:27 +08:00
timer - > initWithCallback ( this , callback , target , key , interval , repeat , delay ) ;
2014-02-20 10:53:49 +08:00
ccArrayAppendObject ( element - > timers , timer ) ;
timer - > release ( ) ;
2012-02-01 16:45:23 +08:00
}
2014-03-03 11:00:30 +08:00
void Scheduler : : unschedule ( const std : : string & key , void * target )
2012-02-01 16:45:23 +08:00
{
2015-09-22 16:08:23 +08:00
// explicit handle nil arguments when removing an object
2014-03-01 13:30:20 +08:00
if ( target = = nullptr | | key . empty ( ) )
2012-04-19 14:35:52 +08:00
{
return ;
}
2013-07-20 13:01:27 +08:00
//CCASSERT(target);
//CCASSERT(selector);
2012-04-19 14:35:52 +08:00
2013-11-16 21:08:00 +08:00
tHashTimerEntry * element = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForTimers , & target , element ) ;
2012-04-19 14:35:52 +08:00
2013-07-18 07:56:19 +08:00
if ( element )
2012-04-19 14:35:52 +08:00
{
2013-09-08 11:26:38 +08:00
for ( int i = 0 ; i < element - > timers - > num ; + + i )
2012-04-19 14:35:52 +08:00
{
2015-05-28 10:53:46 +08:00
TimerTargetCallback * timer = dynamic_cast < TimerTargetCallback * > ( element - > timers - > arr [ i ] ) ;
2012-04-19 14:35:52 +08:00
2015-05-28 10:53:46 +08:00
if ( timer & & key = = timer - > getKey ( ) )
2012-04-19 14:35:52 +08:00
{
2013-11-16 21:08:00 +08:00
if ( timer = = element - > currentTimer & & ( ! element - > currentTimerSalvaged ) )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
element - > currentTimer - > retain ( ) ;
element - > currentTimerSalvaged = true ;
2012-04-19 14:35:52 +08:00
}
2013-07-18 07:56:19 +08:00
ccArrayRemoveObjectAtIndex ( element - > timers , i , true ) ;
2012-04-19 14:35:52 +08:00
// update timerIndex in case we are in tick:, looping over the actions
2013-07-18 07:56:19 +08:00
if ( element - > timerIndex > = i )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
element - > timerIndex - - ;
2012-04-19 14:35:52 +08:00
}
2013-07-18 07:56:19 +08:00
if ( element - > timers - > num = = 0 )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
if ( _currentTarget = = element )
2012-04-19 14:35:52 +08:00
{
2013-06-15 14:03:30 +08:00
_currentTargetSalvaged = true ;
2012-04-19 14:35:52 +08:00
}
else
{
2013-07-18 07:56:19 +08:00
removeHashElement ( element ) ;
2012-04-19 14:35:52 +08:00
}
}
return ;
}
}
}
2012-02-01 16:45:23 +08:00
}
2014-02-20 14:11:47 +08:00
void Scheduler : : priorityIn ( tListEntry * * list , const ccSchedulerFunc & callback , void * target , int priority , bool paused )
2012-02-01 16:45:23 +08:00
{
2015-12-16 14:02:55 +08:00
tListEntry * listElement = new ( std : : nothrow ) tListEntry ( ) ;
2012-04-19 14:35:52 +08:00
2014-02-20 10:53:49 +08:00
listElement - > callback = callback ;
2013-07-18 07:56:19 +08:00
listElement - > target = target ;
listElement - > priority = priority ;
listElement - > paused = paused ;
2013-11-16 21:08:00 +08:00
listElement - > next = listElement - > prev = nullptr ;
2013-07-18 07:56:19 +08:00
listElement - > markedForDeletion = false ;
2012-04-19 14:35:52 +08:00
2012-09-16 05:19:14 +08:00
// empty list ?
2013-07-18 07:56:19 +08:00
if ( ! * list )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
DL_APPEND ( * list , listElement ) ;
2012-04-19 14:35:52 +08:00
}
else
{
2013-11-16 21:08:00 +08:00
bool added = false ;
2012-04-19 14:35:52 +08:00
2013-07-18 07:56:19 +08:00
for ( tListEntry * element = * list ; element ; element = element - > next )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
if ( priority < element - > priority )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
if ( element = = * list )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
DL_PREPEND ( * list , listElement ) ;
2012-04-19 14:35:52 +08:00
}
else
{
2013-07-18 07:56:19 +08:00
listElement - > next = element ;
listElement - > prev = element - > prev ;
2012-04-19 14:35:52 +08:00
2013-07-18 07:56:19 +08:00
element - > prev - > next = listElement ;
element - > prev = listElement ;
2012-04-19 14:35:52 +08:00
}
2013-11-16 21:08:00 +08:00
added = true ;
2012-04-19 14:35:52 +08:00
break ;
}
}
// Not added? priority has the higher value. Append it.
2013-11-16 21:08:00 +08:00
if ( ! added )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
DL_APPEND ( * list , listElement ) ;
2012-04-19 14:35:52 +08:00
}
}
// update hash entry for quick access
2013-11-16 21:08:00 +08:00
tHashUpdateEntry * hashElement = ( tHashUpdateEntry * ) calloc ( sizeof ( * hashElement ) , 1 ) ;
hashElement - > target = target ;
hashElement - > list = list ;
hashElement - > entry = listElement ;
HASH_ADD_PTR ( _hashForUpdates , target , hashElement ) ;
2012-02-01 16:45:23 +08:00
}
2014-02-20 14:11:47 +08:00
void Scheduler : : appendIn ( _listEntry * * list , const ccSchedulerFunc & callback , void * target , bool paused )
2012-02-01 16:45:23 +08:00
{
2015-12-16 14:02:55 +08:00
tListEntry * listElement = new ( std : : nothrow ) tListEntry ( ) ;
2012-02-01 16:45:23 +08:00
2014-02-20 10:53:49 +08:00
listElement - > callback = callback ;
2013-07-18 07:56:19 +08:00
listElement - > target = target ;
listElement - > paused = paused ;
2014-11-18 22:05:56 +08:00
listElement - > priority = 0 ;
2013-07-18 07:56:19 +08:00
listElement - > markedForDeletion = false ;
2012-02-01 16:45:23 +08:00
2013-07-18 07:56:19 +08:00
DL_APPEND ( * list , listElement ) ;
2012-02-01 16:45:23 +08:00
2012-04-19 14:35:52 +08:00
// update hash entry for quicker access
2013-12-18 17:47:20 +08:00
tHashUpdateEntry * hashElement = ( tHashUpdateEntry * ) calloc ( sizeof ( * hashElement ) , 1 ) ;
hashElement - > target = target ;
hashElement - > list = list ;
hashElement - > entry = listElement ;
HASH_ADD_PTR ( _hashForUpdates , target , hashElement ) ;
2012-02-01 16:45:23 +08:00
}
2014-03-03 11:00:30 +08:00
void Scheduler : : schedulePerFrame ( const ccSchedulerFunc & callback , void * target , int priority , bool paused )
2012-02-01 16:45:23 +08:00
{
2013-11-16 21:08:00 +08:00
tHashUpdateEntry * hashElement = nullptr ;
HASH_FIND_PTR ( _hashForUpdates , & target , hashElement ) ;
if ( hashElement )
2012-04-19 14:35:52 +08:00
{
2017-01-16 17:37:59 +08:00
// change priority: should unschedule it first
if ( hashElement - > entry - > priority ! = priority )
2014-05-29 13:51:43 +08:00
{
2017-01-16 17:37:59 +08:00
unscheduleUpdate ( target ) ;
2014-05-29 13:51:43 +08:00
}
else
{
2017-01-16 17:37:59 +08:00
// don't add it again
CCLOG ( " warning: don't update it again " ) ;
2014-05-29 13:51:43 +08:00
return ;
}
2012-04-19 14:35:52 +08:00
}
// most of the updates are going to be 0, that's way there
// is an special list for updates with priority 0
2013-07-18 07:56:19 +08:00
if ( priority = = 0 )
2012-04-19 14:35:52 +08:00
{
2014-02-20 10:53:49 +08:00
appendIn ( & _updates0List , callback , target , paused ) ;
2013-03-18 15:29:53 +08:00
}
2013-07-18 07:56:19 +08:00
else if ( priority < 0 )
2012-04-19 14:35:52 +08:00
{
2014-02-20 10:53:49 +08:00
priorityIn ( & _updatesNegList , callback , target , priority , paused ) ;
2012-04-19 14:35:52 +08:00
}
else
{
// priority > 0
2014-02-20 10:53:49 +08:00
priorityIn ( & _updatesPosList , callback , target , priority , paused ) ;
2012-04-19 14:35:52 +08:00
}
2012-02-01 16:45:23 +08:00
}
2014-03-03 11:00:30 +08:00
bool Scheduler : : isScheduled ( const std : : string & key , void * target )
2013-06-27 12:05:47 +08:00
{
2014-03-01 13:30:20 +08:00
CCASSERT ( ! key . empty ( ) , " Argument key must not be empty " ) ;
2013-11-16 21:08:00 +08:00
CCASSERT ( target , " Argument target must be non-nullptr " ) ;
2013-06-27 12:05:47 +08:00
2013-11-16 21:08:00 +08:00
tHashTimerEntry * element = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForTimers , & target , element ) ;
2013-06-27 12:05:47 +08:00
2013-07-18 07:56:19 +08:00
if ( ! element )
2013-06-27 12:05:47 +08:00
{
return false ;
}
2013-11-16 21:08:00 +08:00
if ( element - > timers = = nullptr )
2013-06-27 12:05:47 +08:00
{
return false ;
2014-03-01 13:30:20 +08:00
}
else
2013-06-27 12:05:47 +08:00
{
2013-09-08 11:26:38 +08:00
for ( int i = 0 ; i < element - > timers - > num ; + + i )
2013-06-27 12:05:47 +08:00
{
2015-05-28 10:53:46 +08:00
TimerTargetCallback * timer = dynamic_cast < TimerTargetCallback * > ( element - > timers - > arr [ i ] ) ;
2013-06-27 12:05:47 +08:00
2015-05-28 10:53:46 +08:00
if ( timer & & key = = timer - > getKey ( ) )
2013-06-27 12:05:47 +08:00
{
return true ;
}
}
return false ;
}
return false ; // should never get here
}
2013-06-20 14:13:12 +08:00
void Scheduler : : removeUpdateFromHash ( struct _listEntry * entry )
2012-02-01 16:45:23 +08:00
{
2013-11-16 21:08:00 +08:00
tHashUpdateEntry * element = nullptr ;
2012-04-19 14:35:52 +08:00
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForUpdates , & entry - > target , element ) ;
2012-04-19 14:35:52 +08:00
if ( element )
{
// list entry
DL_DELETE ( * element - > list , element - > entry ) ;
2017-01-16 17:37:59 +08:00
if ( ! _updateHashLocked )
CC_SAFE_DELETE ( element - > entry ) ;
else
2017-01-18 16:32:36 +08:00
{
element - > entry - > markedForDeletion = true ;
2017-01-16 17:37:59 +08:00
_updateDeleteVector . push_back ( element - > entry ) ;
2017-01-18 16:32:36 +08:00
}
2012-04-19 14:35:52 +08:00
// hash entry
2013-06-15 14:03:30 +08:00
HASH_DEL ( _hashForUpdates , element ) ;
2012-04-19 14:35:52 +08:00
free ( element ) ;
}
2012-02-01 16:45:23 +08:00
}
2014-03-03 11:00:30 +08:00
void Scheduler : : unscheduleUpdate ( void * target )
2012-02-01 16:45:23 +08:00
{
2013-11-16 21:08:00 +08:00
if ( target = = nullptr )
2012-04-19 14:35:52 +08:00
{
return ;
}
2013-11-16 21:08:00 +08:00
tHashUpdateEntry * element = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForUpdates , & target , element ) ;
2013-07-18 07:56:19 +08:00
if ( element )
2017-01-16 17:37:59 +08:00
this - > removeUpdateFromHash ( element - > entry ) ;
2012-02-01 16:45:23 +08:00
}
2013-06-20 14:13:12 +08:00
void Scheduler : : unscheduleAll ( void )
2012-06-08 14:11:48 +08:00
{
2013-07-25 21:04:32 +08:00
unscheduleAllWithMinPriority ( PRIORITY_SYSTEM ) ;
2012-06-08 14:11:48 +08:00
}
2013-11-16 21:08:00 +08:00
void Scheduler : : unscheduleAllWithMinPriority ( int minPriority )
2012-02-01 16:45:23 +08:00
{
2012-04-19 14:35:52 +08:00
// Custom Selectors
2013-11-16 21:08:00 +08:00
tHashTimerEntry * element = nullptr ;
tHashTimerEntry * nextElement = nullptr ;
for ( element = _hashForTimers ; element ! = nullptr ; )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
// element may be removed in unscheduleAllSelectorsForTarget
2013-11-16 21:08:00 +08:00
nextElement = ( tHashTimerEntry * ) element - > hh . next ;
2013-07-18 07:56:19 +08:00
unscheduleAllForTarget ( element - > target ) ;
2012-02-01 16:45:23 +08:00
2013-11-16 21:08:00 +08:00
element = nextElement ;
2012-04-19 14:35:52 +08:00
}
// Updates selectors
2013-11-11 12:49:38 +08:00
tListEntry * entry , * tmp ;
2013-11-16 21:08:00 +08:00
if ( minPriority < 0 )
2012-04-19 14:35:52 +08:00
{
2013-11-11 12:49:38 +08:00
DL_FOREACH_SAFE ( _updatesNegList , entry , tmp )
2012-06-08 14:11:48 +08:00
{
2013-11-16 21:08:00 +08:00
if ( entry - > priority > = minPriority )
2012-06-08 14:11:48 +08:00
{
2014-03-03 11:00:30 +08:00
unscheduleUpdate ( entry - > target ) ;
2012-06-08 14:11:48 +08:00
}
}
2012-04-19 14:35:52 +08:00
}
2012-06-08 14:11:48 +08:00
2013-11-16 21:08:00 +08:00
if ( minPriority < = 0 )
2012-04-19 14:35:52 +08:00
{
2013-11-11 12:49:38 +08:00
DL_FOREACH_SAFE ( _updates0List , entry , tmp )
2012-06-08 14:11:48 +08:00
{
2014-03-03 11:00:30 +08:00
unscheduleUpdate ( entry - > target ) ;
2012-06-08 14:11:48 +08:00
}
2012-04-19 14:35:52 +08:00
}
2012-06-08 14:11:48 +08:00
2013-11-11 12:49:38 +08:00
DL_FOREACH_SAFE ( _updatesPosList , entry , tmp )
2012-04-19 14:35:52 +08:00
{
2013-11-16 21:08:00 +08:00
if ( entry - > priority > = minPriority )
2012-06-08 14:11:48 +08:00
{
2014-03-03 11:00:30 +08:00
unscheduleUpdate ( entry - > target ) ;
2012-06-08 14:11:48 +08:00
}
2012-04-19 14:35:52 +08:00
}
2014-02-20 16:40:46 +08:00
# if CC_ENABLE_SCRIPT_BINDING
2013-12-07 14:25:24 +08:00
_scriptHandlerEntries . clear ( ) ;
2014-02-20 16:40:46 +08:00
# endif
2012-02-09 14:07:11 +08:00
}
2012-02-01 16:45:23 +08:00
2014-02-20 14:11:47 +08:00
void Scheduler : : unscheduleAllForTarget ( void * target )
2012-02-01 16:45:23 +08:00
{
2013-11-16 21:08:00 +08:00
// explicit nullptr handling
if ( target = = nullptr )
2012-04-19 14:35:52 +08:00
{
return ;
}
// Custom Selectors
2013-11-16 21:08:00 +08:00
tHashTimerEntry * element = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForTimers , & target , element ) ;
2012-04-19 14:35:52 +08:00
2013-07-18 07:56:19 +08:00
if ( element )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
if ( ccArrayContainsObject ( element - > timers , element - > currentTimer )
& & ( ! element - > currentTimerSalvaged ) )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
element - > currentTimer - > retain ( ) ;
element - > currentTimerSalvaged = true ;
2012-04-19 14:35:52 +08:00
}
2013-07-18 07:56:19 +08:00
ccArrayRemoveAllObjects ( element - > timers ) ;
2012-04-19 14:35:52 +08:00
2013-07-18 07:56:19 +08:00
if ( _currentTarget = = element )
2012-04-19 14:35:52 +08:00
{
2013-06-15 14:03:30 +08:00
_currentTargetSalvaged = true ;
2012-04-19 14:35:52 +08:00
}
else
{
2013-07-18 07:56:19 +08:00
removeHashElement ( element ) ;
2012-04-19 14:35:52 +08:00
}
}
// update selector
2014-03-03 11:00:30 +08:00
unscheduleUpdate ( target ) ;
2012-02-01 16:45:23 +08:00
}
2014-02-20 16:40:46 +08:00
# if CC_ENABLE_SCRIPT_BINDING
2013-07-18 07:56:19 +08:00
unsigned int Scheduler : : scheduleScriptFunc ( unsigned int handler , float interval , bool paused )
2012-02-02 15:58:10 +08:00
{
2013-11-16 21:08:00 +08:00
SchedulerScriptHandlerEntry * entry = SchedulerScriptHandlerEntry : : create ( handler , interval , paused ) ;
2013-12-07 14:25:24 +08:00
_scriptHandlerEntries . pushBack ( entry ) ;
2013-11-16 21:08:00 +08:00
return entry - > getEntryId ( ) ;
2012-02-02 15:58:10 +08:00
}
2013-11-16 21:08:00 +08:00
void Scheduler : : unscheduleScriptEntry ( unsigned int scheduleScriptEntryID )
2012-02-02 15:58:10 +08:00
{
2013-12-12 12:07:20 +08:00
for ( ssize_t i = _scriptHandlerEntries . size ( ) - 1 ; i > = 0 ; i - - )
2012-02-02 15:58:10 +08:00
{
2013-12-07 14:25:24 +08:00
SchedulerScriptHandlerEntry * entry = _scriptHandlerEntries . at ( i ) ;
2013-11-16 21:08:00 +08:00
if ( entry - > getEntryId ( ) = = ( int ) scheduleScriptEntryID )
2012-02-02 15:58:10 +08:00
{
2013-11-16 21:08:00 +08:00
entry - > markedForDeletion ( ) ;
2012-02-02 15:58:10 +08:00
break ;
}
}
}
2014-02-20 16:40:46 +08:00
# endif
2014-02-20 14:11:47 +08:00
void Scheduler : : resumeTarget ( void * target )
2012-02-01 16:45:23 +08:00
{
2015-07-14 15:28:36 +08:00
CCASSERT ( target ! = nullptr , " target can't be nullptr! " ) ;
2012-04-19 14:35:52 +08:00
// custom selectors
2013-11-16 21:08:00 +08:00
tHashTimerEntry * element = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForTimers , & target , element ) ;
2013-07-18 07:56:19 +08:00
if ( element )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
element - > paused = false ;
2012-04-19 14:35:52 +08:00
}
// update selector
2013-11-16 21:08:00 +08:00
tHashUpdateEntry * elementUpdate = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForUpdates , & target , elementUpdate ) ;
2013-07-18 07:56:19 +08:00
if ( elementUpdate )
2012-04-19 14:35:52 +08:00
{
2015-07-14 15:28:36 +08:00
CCASSERT ( elementUpdate - > entry ! = nullptr , " elementUpdate's entry can't be nullptr! " ) ;
2013-07-18 07:56:19 +08:00
elementUpdate - > entry - > paused = false ;
2012-04-19 14:35:52 +08:00
}
2012-02-01 16:45:23 +08:00
}
2014-02-20 14:11:47 +08:00
void Scheduler : : pauseTarget ( void * target )
2012-02-01 16:45:23 +08:00
{
2015-07-14 15:28:36 +08:00
CCASSERT ( target ! = nullptr , " target can't be nullptr! " ) ;
2012-04-19 14:35:52 +08:00
// custom selectors
2013-11-16 21:08:00 +08:00
tHashTimerEntry * element = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForTimers , & target , element ) ;
2013-07-18 07:56:19 +08:00
if ( element )
2012-04-19 14:35:52 +08:00
{
2013-07-18 07:56:19 +08:00
element - > paused = true ;
2012-04-19 14:35:52 +08:00
}
// update selector
2013-11-16 21:08:00 +08:00
tHashUpdateEntry * elementUpdate = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForUpdates , & target , elementUpdate ) ;
2013-07-18 07:56:19 +08:00
if ( elementUpdate )
2012-04-19 14:35:52 +08:00
{
2015-07-14 15:28:36 +08:00
CCASSERT ( elementUpdate - > entry ! = nullptr , " elementUpdate's entry can't be nullptr! " ) ;
2013-07-18 07:56:19 +08:00
elementUpdate - > entry - > paused = true ;
2012-04-19 14:35:52 +08:00
}
2012-02-01 16:45:23 +08:00
}
2014-02-20 14:11:47 +08:00
bool Scheduler : : isTargetPaused ( void * target )
2012-02-01 16:45:23 +08:00
{
2013-11-16 21:08:00 +08:00
CCASSERT ( target ! = nullptr , " target must be non nil " ) ;
2012-02-01 16:45:23 +08:00
// Custom selectors
2013-11-16 21:08:00 +08:00
tHashTimerEntry * element = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForTimers , & target , element ) ;
2013-07-18 07:56:19 +08:00
if ( element )
2012-02-01 16:45:23 +08:00
{
2013-07-18 07:56:19 +08:00
return element - > paused ;
2012-02-01 16:45:23 +08:00
}
2012-11-14 18:05:15 +08:00
// We should check update selectors if target does not have custom selectors
2013-11-16 21:08:00 +08:00
tHashUpdateEntry * elementUpdate = nullptr ;
2013-11-11 12:47:48 +08:00
HASH_FIND_PTR ( _hashForUpdates , & target , elementUpdate ) ;
2012-11-14 18:05:15 +08:00
if ( elementUpdate )
{
return elementUpdate - > entry - > paused ;
}
2012-02-01 16:45:23 +08:00
return false ; // should never get here
}
2014-02-20 14:11:47 +08:00
std : : set < void * > Scheduler : : pauseAllTargets ( )
2012-06-14 05:26:28 +08:00
{
2013-07-25 21:04:32 +08:00
return pauseAllTargetsWithMinPriority ( PRIORITY_SYSTEM ) ;
2012-06-14 05:26:28 +08:00
}
2014-02-20 14:11:47 +08:00
std : : set < void * > Scheduler : : pauseAllTargetsWithMinPriority ( int minPriority )
2012-06-14 05:26:28 +08:00
{
2014-02-20 14:11:47 +08:00
std : : set < void * > idsWithSelectors ;
2012-06-14 05:26:28 +08:00
// Custom Selectors
2013-11-16 21:08:00 +08:00
for ( tHashTimerEntry * element = _hashForTimers ; element ! = nullptr ;
2012-11-14 18:05:15 +08:00
element = ( tHashTimerEntry * ) element - > hh . next )
2012-06-14 05:26:28 +08:00
{
element - > paused = true ;
2014-02-20 14:11:47 +08:00
idsWithSelectors . insert ( element - > target ) ;
2012-06-14 05:26:28 +08:00
}
// Updates selectors
tListEntry * entry , * tmp ;
2013-11-16 21:08:00 +08:00
if ( minPriority < 0 )
2012-06-14 05:26:28 +08:00
{
2013-06-15 14:03:30 +08:00
DL_FOREACH_SAFE ( _updatesNegList , entry , tmp )
2012-06-14 05:26:28 +08:00
{
2013-11-16 21:08:00 +08:00
if ( entry - > priority > = minPriority )
2012-06-14 05:26:28 +08:00
{
entry - > paused = true ;
2014-02-20 14:11:47 +08:00
idsWithSelectors . insert ( entry - > target ) ;
2012-06-14 05:26:28 +08:00
}
}
}
2013-11-16 21:08:00 +08:00
if ( minPriority < = 0 )
2012-06-14 05:26:28 +08:00
{
2013-06-15 14:03:30 +08:00
DL_FOREACH_SAFE ( _updates0List , entry , tmp )
2012-06-14 05:26:28 +08:00
{
entry - > paused = true ;
2014-02-20 14:11:47 +08:00
idsWithSelectors . insert ( entry - > target ) ;
2012-06-14 05:26:28 +08:00
}
}
2013-06-15 14:03:30 +08:00
DL_FOREACH_SAFE ( _updatesPosList , entry , tmp )
2012-06-14 05:26:28 +08:00
{
2013-11-16 21:08:00 +08:00
if ( entry - > priority > = minPriority )
2012-06-14 05:26:28 +08:00
{
entry - > paused = true ;
2014-02-20 14:11:47 +08:00
idsWithSelectors . insert ( entry - > target ) ;
2012-06-14 05:26:28 +08:00
}
}
2013-12-10 16:06:05 +08:00
return idsWithSelectors ;
2012-06-14 05:26:28 +08:00
}
2014-02-20 14:11:47 +08:00
void Scheduler : : resumeTargets ( const std : : set < void * > & targetsToResume )
2012-06-14 05:26:28 +08:00
{
2013-12-20 05:34:41 +08:00
for ( const auto & obj : targetsToResume ) {
2013-12-06 18:16:58 +08:00
this - > resumeTarget ( obj ) ;
2013-12-20 05:34:41 +08:00
}
2012-06-08 14:11:48 +08:00
}
2013-11-27 08:58:14 +08:00
void Scheduler : : performFunctionInCocosThread ( const std : : function < void ( ) > & function )
{
_performMutex . lock ( ) ;
_functionsToPerform . push_back ( function ) ;
_performMutex . unlock ( ) ;
}
2016-12-08 11:58:58 +08:00
void Scheduler : : removeAllFunctionsToBePerformedInCocosThread ( )
{
std : : unique_lock < std : : mutex > lock ( _performMutex ) ;
_functionsToPerform . clear ( ) ;
}
2012-02-01 16:45:23 +08:00
// main loop
2013-06-20 14:13:12 +08:00
void Scheduler : : update ( float dt )
2012-02-01 16:45:23 +08:00
{
2013-06-15 14:03:30 +08:00
_updateHashLocked = true ;
2012-04-19 14:35:52 +08:00
2013-06-15 14:03:30 +08:00
if ( _timeScale ! = 1.0f )
2012-04-19 14:35:52 +08:00
{
2013-06-15 14:03:30 +08:00
dt * = _timeScale ;
2012-04-19 14:35:52 +08:00
}
2013-11-27 08:58:14 +08:00
//
// Selector callbacks
//
2012-09-16 05:19:14 +08:00
// Iterate over all the Updates' selectors
2013-11-11 12:49:38 +08:00
tListEntry * entry , * tmp ;
2012-04-19 14:35:52 +08:00
// updates with priority < 0
2013-11-11 12:49:38 +08:00
DL_FOREACH_SAFE ( _updatesNegList , entry , tmp )
2012-04-19 14:35:52 +08:00
{
2013-11-11 12:49:38 +08:00
if ( ( ! entry - > paused ) & & ( ! entry - > markedForDeletion ) )
2012-04-19 14:35:52 +08:00
{
2014-02-20 10:53:49 +08:00
entry - > callback ( dt ) ;
2012-04-19 14:35:52 +08:00
}
}
// updates with priority == 0
2013-11-11 12:49:38 +08:00
DL_FOREACH_SAFE ( _updates0List , entry , tmp )
2012-04-19 14:35:52 +08:00
{
2013-11-11 12:49:38 +08:00
if ( ( ! entry - > paused ) & & ( ! entry - > markedForDeletion ) )
2012-04-19 14:35:52 +08:00
{
2014-02-20 10:53:49 +08:00
entry - > callback ( dt ) ;
2012-04-19 14:35:52 +08:00
}
}
// updates with priority > 0
2013-11-11 12:49:38 +08:00
DL_FOREACH_SAFE ( _updatesPosList , entry , tmp )
2012-04-19 14:35:52 +08:00
{
2013-11-11 12:49:38 +08:00
if ( ( ! entry - > paused ) & & ( ! entry - > markedForDeletion ) )
2012-04-19 14:35:52 +08:00
{
2014-02-20 10:53:49 +08:00
entry - > callback ( dt ) ;
2012-04-19 14:35:52 +08:00
}
}
2012-09-16 05:19:14 +08:00
// Iterate over all the custom selectors
2013-11-16 21:08:00 +08:00
for ( tHashTimerEntry * elt = _hashForTimers ; elt ! = nullptr ; )
2012-04-19 14:35:52 +08:00
{
2013-06-15 14:03:30 +08:00
_currentTarget = elt ;
_currentTargetSalvaged = false ;
2012-04-19 14:35:52 +08:00
2013-06-15 14:03:30 +08:00
if ( ! _currentTarget - > paused )
2012-04-19 14:35:52 +08:00
{
// The 'timers' array may change while inside this loop
for ( elt - > timerIndex = 0 ; elt - > timerIndex < elt - > timers - > num ; + + ( elt - > timerIndex ) )
{
2013-06-20 14:13:12 +08:00
elt - > currentTimer = ( Timer * ) ( elt - > timers - > arr [ elt - > timerIndex ] ) ;
2012-04-19 14:35:52 +08:00
elt - > currentTimerSalvaged = false ;
elt - > currentTimer - > update ( dt ) ;
if ( elt - > currentTimerSalvaged )
{
// 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 ( ) ;
}
2013-11-16 21:08:00 +08:00
elt - > currentTimer = nullptr ;
2012-04-19 14:35:52 +08:00
}
}
// elt, at this moment, is still valid
// so it is safe to ask this here (issue #490)
2012-11-14 18:05:15 +08:00
elt = ( tHashTimerEntry * ) elt - > hh . next ;
2012-04-19 14:35:52 +08:00
// only delete currentTarget if no actions were scheduled during the cycle (issue #481)
2013-06-15 14:03:30 +08:00
if ( _currentTargetSalvaged & & _currentTarget - > timers - > num = = 0 )
2012-04-19 14:35:52 +08:00
{
2013-06-15 14:03:30 +08:00
removeHashElement ( _currentTarget ) ;
2012-04-19 14:35:52 +08:00
}
}
2017-01-16 17:37:59 +08:00
// delete all updates that are removed in update
for ( auto & e : _updateDeleteVector )
delete e ;
2012-02-06 10:54:51 +08:00
2017-01-16 17:37:59 +08:00
_updateDeleteVector . clear ( ) ;
2012-04-19 14:35:52 +08:00
2013-06-15 14:03:30 +08:00
_updateHashLocked = false ;
2013-11-16 21:08:00 +08:00
_currentTarget = nullptr ;
2013-11-27 08:58:14 +08:00
2014-02-20 16:40:46 +08:00
# if CC_ENABLE_SCRIPT_BINDING
2013-11-27 08:58:14 +08:00
//
// Script callbacks
//
// Iterate over all the script callbacks
2013-12-07 14:25:24 +08:00
if ( ! _scriptHandlerEntries . empty ( ) )
2013-11-27 08:58:14 +08:00
{
2013-12-07 14:25:24 +08:00
for ( auto i = _scriptHandlerEntries . size ( ) - 1 ; i > = 0 ; i - - )
2013-11-27 08:58:14 +08:00
{
2013-12-07 14:25:24 +08:00
SchedulerScriptHandlerEntry * eachEntry = _scriptHandlerEntries . at ( i ) ;
2013-11-27 08:58:14 +08:00
if ( eachEntry - > isMarkedForDeletion ( ) )
{
2013-12-11 17:53:45 +08:00
_scriptHandlerEntries . erase ( i ) ;
2013-11-27 08:58:14 +08:00
}
else if ( ! eachEntry - > isPaused ( ) )
{
eachEntry - > getTimer ( ) - > update ( dt ) ;
}
}
}
2014-02-20 16:40:46 +08:00
# endif
2013-11-27 08:58:14 +08:00
//
// Functions allocated from another thread
//
// Testing size is faster than locking / unlocking.
// And almost never there will be functions scheduled to be called.
2013-12-05 13:51:08 +08:00
if ( ! _functionsToPerform . empty ( ) ) {
2013-11-27 08:58:14 +08:00
_performMutex . lock ( ) ;
2014-02-24 21:08:05 +08:00
// 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 = _functionsToPerform ;
2013-11-27 08:58:14 +08:00
_functionsToPerform . clear ( ) ;
_performMutex . unlock ( ) ;
2014-02-24 21:08:05 +08:00
for ( const auto & function : temp ) {
function ( ) ;
}
2013-11-27 08:58:14 +08:00
}
2012-02-01 16:45:23 +08:00
}
2012-03-14 14:55:17 +08:00
2014-03-03 11:00:30 +08:00
void Scheduler : : schedule ( SEL_SCHEDULE selector , Ref * target , float interval , unsigned int repeat , float delay , bool paused )
2014-02-20 10:53:49 +08:00
{
2014-03-01 13:30:20 +08:00
CCASSERT ( target , " Argument target must be non-nullptr " ) ;
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
{
2015-07-14 15:28:36 +08:00
CCASSERT ( element - > paused = = paused , " element's paused should be paused. " ) ;
2014-03-01 13:30:20 +08:00
}
if ( element - > timers = = nullptr )
{
element - > timers = ccArrayNew ( 10 ) ;
}
else
{
for ( int i = 0 ; i < element - > timers - > num ; + + i )
{
2015-01-27 17:29:12 +08:00
TimerTargetSelector * timer = dynamic_cast < TimerTargetSelector * > ( element - > timers - > arr [ i ] ) ;
2014-03-01 13:30:20 +08:00
2015-01-27 17:29:12 +08:00
if ( timer & & selector = = timer - > getSelector ( ) )
2014-03-01 13:30:20 +08:00
{
CCLOG ( " CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f " , timer - > getInterval ( ) , interval ) ;
timer - > setInterval ( interval ) ;
return ;
}
}
ccArrayEnsureExtraCapacity ( element - > timers , 1 ) ;
}
2014-08-28 07:31:57 +08:00
TimerTargetSelector * timer = new ( std : : nothrow ) TimerTargetSelector ( ) ;
2014-03-03 17:51:27 +08:00
timer - > initWithSelector ( this , selector , target , interval , repeat , delay ) ;
2014-03-01 13:30:20 +08:00
ccArrayAppendObject ( element - > timers , timer ) ;
timer - > release ( ) ;
2014-02-20 10:53:49 +08:00
}
2014-03-03 11:00:30 +08:00
void Scheduler : : schedule ( SEL_SCHEDULE selector , Ref * target , float interval , bool paused )
2014-02-20 10:53:49 +08:00
{
2014-10-04 00:38:36 +08:00
this - > schedule ( selector , target , interval , CC_REPEAT_FOREVER , 0.0f , paused ) ;
2014-02-20 10:53:49 +08:00
}
2014-03-03 11:00:30 +08:00
bool Scheduler : : isScheduled ( SEL_SCHEDULE selector , Ref * target )
2014-02-20 10:53:49 +08:00
{
2014-03-01 13:30:20 +08:00
CCASSERT ( selector , " Argument selector must be non-nullptr " ) ;
CCASSERT ( target , " Argument target must be non-nullptr " ) ;
tHashTimerEntry * element = nullptr ;
HASH_FIND_PTR ( _hashForTimers , & target , element ) ;
if ( ! element )
{
return false ;
}
if ( element - > timers = = nullptr )
{
return false ;
}
else
{
for ( int i = 0 ; i < element - > timers - > num ; + + i )
{
2015-05-28 10:53:46 +08:00
TimerTargetSelector * timer = dynamic_cast < TimerTargetSelector * > ( element - > timers - > arr [ i ] ) ;
2014-03-01 13:30:20 +08:00
2015-05-28 10:53:46 +08:00
if ( timer & & selector = = timer - > getSelector ( ) )
2014-03-01 13:30:20 +08:00
{
return true ;
}
}
return false ;
}
return false ; // should never get here
2014-02-20 10:53:49 +08:00
}
2014-03-03 11:00:30 +08:00
void Scheduler : : unschedule ( SEL_SCHEDULE selector , Ref * target )
2014-02-20 10:53:49 +08:00
{
2015-09-22 16:08:23 +08:00
// explicit handle nil arguments when removing an object
2014-03-01 13:30:20 +08:00
if ( target = = nullptr | | selector = = nullptr )
{
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 )
{
2015-05-28 10:53:46 +08:00
TimerTargetSelector * timer = dynamic_cast < TimerTargetSelector * > ( element - > timers - > arr [ i ] ) ;
2014-03-01 13:30:20 +08:00
2015-05-28 10:53:46 +08:00
if ( timer & & selector = = timer - > getSelector ( ) )
2014-03-01 13:30:20 +08:00
{
if ( timer = = element - > currentTimer & & ( ! element - > currentTimerSalvaged ) )
{
element - > currentTimer - > retain ( ) ;
element - > currentTimerSalvaged = true ;
}
ccArrayRemoveObjectAtIndex ( element - > timers , i , true ) ;
// update timerIndex in case we are in tick:, looping over the actions
if ( element - > timerIndex > = i )
{
element - > timerIndex - - ;
}
if ( element - > timers - > num = = 0 )
{
if ( _currentTarget = = element )
{
_currentTargetSalvaged = true ;
}
else
{
removeHashElement ( element ) ;
}
}
return ;
}
}
}
2014-02-20 10:53:49 +08:00
}
2012-03-14 14:55:17 +08:00
2012-04-18 18:43:45 +08:00
NS_CC_END