OSDN Git Service

Version 0.6.96. add lock function @X.EventDispatcher.
[pettanr/clientJs.git] / 0.6.x / js / 01_core / 14_XTimer.js
index 0ab0bd4..9d4a849 100644 (file)
@@ -34,7 +34,9 @@
 // ------------ local variables -------------------------------------------- //\r
 // ------------------------------------------------------------------------- //\r
 \r
-var X_Timer_SET_TIMEOUT   = window.setTimeout,\r
+var X_Timer_now = Date.now || function(){ return +new Date; },\r
+\r
+       X_Timer_SET_TIMEOUT   = window.setTimeout,\r
        X_Timer_CLEAR_TIMEOUT = window.clearTimeout,\r
        \r
        X_Timer_REQ_ANIME_FRAME =\r
@@ -56,11 +58,12 @@ var X_Timer_SET_TIMEOUT   = window.setTimeout,
        X_Timer_INTERVAL_TIME  = 16,\r
        X_Timer_TICKET_LIST    = [],\r
        X_Timer_removal        = null,\r
+       X_Timer_skipUpdate     = false,\r
        X_Timer_uid            = 0,\r
        X_Timer_timerId        = 0,\r
-       X_Timer_next           = 0,\r
-       X_Timer_busyTimeout    = false, \r
-       X_Timer_endTime        = 0, // iOS\r
+       X_Timer_busyTimeout    = false,\r
+       X_Timer_timeStamp      = 0, // setTimeout に登録した時間\r
+       X_Timer_waitTime       = 0,     // 待ち時間\r
        \r
        X_Timer_REQ_FRAME_LIST = [],\r
        X_Timer_requestID      = 0,\r
@@ -71,6 +74,8 @@ var X_Timer_SET_TIMEOUT   = window.setTimeout,
 // ------------------------------------------------------------------------- //\r
 X.Timer = {\r
        \r
+       now : X_Timer_now,\r
+       \r
        add : function( time, opt_count, args1, args2, args3 ){\r
                var list = X_Timer_TICKET_LIST,\r
                        hash, obj;\r
@@ -83,7 +88,7 @@ X.Timer = {
                        opt_count = 0;\r
                };\r
                \r
-               hash = X.Callback._classifyCallbackArgs( args1, args2, args3 );\r
+               hash = X_Callback_classifyCallbackArgs( args1, args2, args3 );\r
                if( !hash ) return -1; // dev only\r
                \r
                if( !hash.k ) hash = { f : hash };\r
@@ -112,10 +117,9 @@ X.Timer = {
                        X_Timer_removal[ uid ] = true;\r
                } else {\r
                        for( ; i; ){\r
-       \r
                                if( ( q = list[ --i ] ).uid === uid ){\r
                                        list.splice( i, 1 );\r
-                                       ( /* q[ INDEX_COUNT ] <= next  || */ l === 1 ) && X_Timer_update();\r
+                                       !X_Timer_skipUpdate && ( q.last <= X_Timer_waitTime || l === 1 ) && X_Timer_update();\r
                                        break;\r
                                };\r
                        };                              \r
@@ -127,14 +131,14 @@ X.Timer = {
                        var i = X_Timer_REQ_FRAME_LIST.length,\r
                                f;\r
                        i === 0 && ( X_Timer_requestID = X_Timer_REQ_ANIME_FRAME( X_Timer_onEnterFrame ) );\r
-                       f = X_Timer_REQ_FRAME_LIST[ i ] = X.Callback._classifyCallbackArgs( args1, args2, args3 );\r
+                       f = X_Timer_REQ_FRAME_LIST[ i ] = X_Callback_classifyCallbackArgs( args1, args2, args3 );\r
                        return f.uid = ++X_Timer_uid;\r
                }) :\r
                (function( args1, args2, args3 ){\r
                        var i = X_Timer_REQ_FRAME_LIST.length,\r
                                f;\r
                        i === 0 && ( X_Timer_requestID = X.Timer.add( 0, 1, X_Timer_onEnterFrame ) );\r
-                       f = X_Timer_REQ_FRAME_LIST[ i ] = X.Callback._classifyCallbackArgs( args1, args2, args3 );\r
+                       f = X_Timer_REQ_FRAME_LIST[ i ] = X_Callback_classifyCallbackArgs( args1, args2, args3 );\r
                        return f.uid = ++X_Timer_uid;\r
                }),\r
        \r
@@ -192,46 +196,50 @@ if( X.UA.IE4 || X.UA.MacIE ){
 };\r
 \r
 function X_Timer_onTimeout(){\r
-       var next  = X_Timer_next,\r
+       var now   = X_Timer_now(),\r
+               minus = ( ( now - X_Timer_timeStamp ) / X_Timer_INTERVAL_TIME | 0 ) || 1,\r
                list  = X_Timer_TICKET_LIST,\r
                i     = 0,\r
                l     = list.length,\r
-               limit = X.getTime() + X_Timer_INTERVAL_TIME / 2,\r
+               limit = X_Timer_now() + X_Timer_INTERVAL_TIME / 2,\r
                heavy,\r
                q, f, c, r, uid;\r
        \r
+       //console.log( '予定時間と発火時間の差:' + ( now - X_Timer_timeStamp - X_Timer_waitTime * X_Timer_INTERVAL_TIME ) + ' -:' + minus + ' next:' + X_Timer_waitTime );\r
+       \r
        if( X_Timer_busyTimeout ){\r
-               alert( 'busy!' );\r
+               alert( 'X_Timer_busyTimeout フラグが立ったまま!エラーの可能性' );\r
        };\r
        \r
        X_Timer_busyTimeout = true;\r
        \r
     for( ; i < l; ++i ){\r
        q = list[ i ];\r
-       if( X_Timer_removal && X_Timer_removal[ q.uid ] ) continue;\r
-               if( 0 < ( q.last -= next ) ) continue;\r
-               if( heavy ){\r
-                       if( q.last <= 0 ) q.last = 1;\r
+       if(\r
+               ( X_Timer_removal && X_Timer_removal[ q.uid ] ) || // timerId は remove 登録されている\r
+                       0 < ( q.last -= minus ) || // 時間が経過していない\r
+                       heavy && ( q.last = 1 ) // 時間は経過したが、ヘビーフラグが立っている\r
+               ){\r
                        continue;\r
                };\r
                c = q.count;\r
                \r
                if( q.k ){\r
-                       q.a = [];\r
-                       r = X.Callback._proxyCallback( q );\r
+                       //q.a = [];\r
+                       r = X_Callback_proxyCallback( q, [] );\r
                } else {\r
                        r = q.f();\r
                };\r
                \r
                //console.log( 'fire....' );\r
                \r
-               if( limit <= X.getTime() ){\r
+               if( limit <= X_Timer_now() ){\r
                        console.log( '******* heavy!' );\r
                        // 関数の実行に時間がかかる場合、次のタイミングに\r
                        heavy = true;\r
                };\r
                \r
-               if( r & X.Callback.UN_LISTEN || c === 1 ){\r
+               if( r & X_Callback_UN_LISTEN || c === 1 ){\r
                        list.splice( i, 1 );\r
                        --i;\r
                        --l;\r
@@ -242,10 +250,13 @@ function X_Timer_onTimeout(){
     };\r
     X_Timer_timerId     = 0;\r
     X_Timer_busyTimeout = false;\r
+    \r
     if( X_Timer_removal ){\r
+       X_Timer_skipUpdate = true;\r
        for( uid in X_Timer_removal ){\r
-               X.Timer.remove( X_Timer_removal[ uid ] );\r
+               X.Timer.remove( uid );\r
        };\r
+       X_Timer_skipUpdate = false;\r
        X_Timer_removal = null;\r
     };\r
     X_Timer_update();\r
@@ -265,23 +276,36 @@ function X_Timer_update(){
        \r
     n = list[ i - 1 ].last;\r
     \r
-    if( n < X_Timer_next || X_Timer_timerId === 0 ){\r
-       X_Timer_timerId && X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
-       X_Timer_timerId = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, X_Timer_INTERVAL_TIME * n );\r
-       X_Timer_endTime = X.getTime() + X_Timer_INTERVAL_TIME * n; // iOS\r
-       X_Timer_next = n;\r
+    if( n < X_Timer_waitTime || X_Timer_timerId === 0 ){\r
+       if( X_Timer_timerId ){\r
+               X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
+               n -= ( X_Timer_now() - X_Timer_timeStamp ) / X_Timer_INTERVAL_TIME | 0;\r
+               0 <= n || ( n = 0 ); // 負の数は 0 に\r
+       };\r
+       X_Timer_timeStamp = X_Timer_now();\r
+       X_Timer_timerId   = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, X_Timer_INTERVAL_TIME * n );\r
+       X_Timer_waitTime  = n;\r
     };\r
 };\r
 \r
+// 大きい -> 小さい\r
+function X_Timer_compareQueue( a, b ){\r
+       return a.last < b.last ? 1 : a.last === b.last ? 0 : -1;\r
+};\r
+\r
 // http://havelog.ayumusato.com/develop/javascript/e528-ios6_scrolling_timer_notcall.html\r
 // iOS6 スクロール中のタイマー発火絡みのバグ備忘\r
 if( X.UA.iOS ){\r
        window.addEventListener( 'scroll', function(){\r
-               var last;\r
+               var last, now;\r
                if( X_Timer_timerId ){\r
-                       window.clearTimeout( X_Timer_timerId );\r
-                       last = X_Timer_endTime - X.getTime();\r
+                       X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
+                       now  = X_Timer_now();\r
+                       last = X_Timer_timeStamp + X_Timer_INTERVAL_TIME * X_Timer_waitTime - now;\r
                        X_Timer_timerId = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, 0 < last ? last : 0 );\r
+                       // 更新\r
+                       X_Timer_timeStamp = now;\r
+                       X_Timer_waitTime  = last / X_Timer_INTERVAL_TIME | 0;\r
                };\r
        });\r
 };\r
@@ -291,19 +315,18 @@ if( X.UA.iOS ){
 function X_Timer_onEnterFrame( time ){\r
        var list = X_Timer_REQ_FRAME_LIST,\r
                l    = list.length,\r
-               i    = 0, q, uid;\r
+               i    = 0, q, uid, args;\r
 \r
-       time = time || X.getTime();\r
+       time = time || X_Timer_now();\r
        X_Timer_busyOnFrame = true;\r
-       // console.log( X.getTime() + ' , ' + time );\r
+       // console.log( X_Timer_now() + ' , ' + time );\r
     for( ; i < l; ++i ){\r
        q = list[ i ];\r
        \r
        if( X_Timer_removal && X_Timer_removal[ q.uid ] ) continue;\r
        \r
                if( q.k ){\r
-                       q.a = [ time ];\r
-                       X.Callback._proxyCallback( q );\r
+                       X_Callback_proxyCallback( q, args || ( args = [ time ] ) );\r
                } else {\r
                        q( time );\r
                };\r
@@ -323,10 +346,4 @@ function X_Timer_onEnterFrame( time ){
     };\r
 };\r
 \r
-// 大きい -> 小さい\r
-function X_Timer_compareQueue( a, b ){\r
-       return a.last < b.last ? 1 : a.last === b.last ? 0 : -1;\r
-};\r
-\r
-\r
 console.log( 'X.Core.Timer' );\r