[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog server/movie_root.cpp server/mo...
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] gnash ChangeLog server/movie_root.cpp server/mo... |
Date: |
Fri, 09 Feb 2007 13:38:50 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Sandro Santilli <strk> 07/02/09 13:38:50
Modified files:
. : ChangeLog
server : movie_root.cpp movie_root.h timers.cpp timers.h
server/asobj : xmlsocket.cpp
testsuite/misc-ming.all: Makefile.am
Added files:
testsuite/misc-ming.all: intervalTest.as
Log message:
* server/movie_root.{cpp,h}: Store Timer objects
by value, not by pointer (make memory management easier);
I might change this in the future, but for now it works
fine. Possible future changes include: reserving a number
of slots for timers (possibly setting a limit), reusing
slots of expired timers (needs a testcase to see if that's
allowed).
* server/timers.{cpp,h}: Big cleanup; got rid of
timer_as_object;
use integer values for times, reduced function calls (store
timeouts
in microseconds directly); documented.
* server/asobj/xmlsocket.cpp: fix use of Timer class.
* testsuite/misc-ming.all/: Makefile.am, intervalTest.as: new
test for setInterval() and clearInterval(). Lacks a test
*runner*
but the manually running it clearly shows it works with this
commit
(and not before). Note that self-contained tests are already
present, but a MovieTester based runner is required for proper
testing.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2287&r2=1.2288
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.cpp?cvsroot=gnash&r1=1.39&r2=1.40
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.h?cvsroot=gnash&r1=1.35&r2=1.36
http://cvs.savannah.gnu.org/viewcvs/gnash/server/timers.cpp?cvsroot=gnash&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/gnash/server/timers.h?cvsroot=gnash&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xmlsocket.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/Makefile.am?cvsroot=gnash&r1=1.62&r2=1.63
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/intervalTest.as?cvsroot=gnash&rev=1.1
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2287
retrieving revision 1.2288
diff -u -b -r1.2287 -r1.2288
--- ChangeLog 9 Feb 2007 13:29:14 -0000 1.2287
+++ ChangeLog 9 Feb 2007 13:38:50 -0000 1.2288
@@ -1,3 +1,23 @@
+2007-02-09 Sandro Santilli <address@hidden>
+
+ * server/movie_root.{cpp,h}: Store Timer objects
+ by value, not by pointer (make memory management easier);
+ I might change this in the future, but for now it works
+ fine. Possible future changes include: reserving a number
+ of slots for timers (possibly setting a limit), reusing
+ slots of expired timers (needs a testcase to see if that's
+ allowed).
+ * server/timers.{cpp,h}: Big cleanup; got rid of timer_as_object;
+ use integer values for times, reduced function calls (store timeouts
+ in microseconds directly); documented.
+ * server/asobj/xmlsocket.cpp: fix use of Timer class.
+ * testsuite/misc-ming.all/: Makefile.am, intervalTest.as: new
+ test for setInterval() and clearInterval(). Lacks a test *runner*
+ but the manually running it clearly shows it works with this commit
+ (and not before). Note that self-contained tests are already
+ present, but a MovieTester based runner is required for proper
+ testing.
+
2007-02-09 Martin Guy <address@hidden>
* server/asobj/Math.cpp: Methods for constants have uppercase names
Index: server/movie_root.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/movie_root.cpp,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -b -r1.39 -r1.40
--- server/movie_root.cpp 9 Feb 2007 00:19:07 -0000 1.39
+++ server/movie_root.cpp 9 Feb 2007 13:38:50 -0000 1.40
@@ -401,29 +401,26 @@
#endif
unsigned int
-movie_root::add_interval_timer(Timer& timer)
+movie_root::add_interval_timer(const Timer& timer)
{
assert(testInvariant());
- int id = _intervalTimers.size();
+ int id = _intervalTimers.size()+1;
// TODO: find first NULL element in vector for reuse ?
- _intervalTimers.push_back(&timer);
+ _intervalTimers.push_back(timer);
return id;
}
bool
movie_root::clear_interval_timer(unsigned int x)
{
- if ( x >= _intervalTimers.size() ) return false;
+ if ( ! x || x > _intervalTimers.size() ) return false;
- Timer* timer = _intervalTimers[x];
+ Timer& timer = _intervalTimers[x-1];
- // Check that _intervalTimers[x] does really exists.
- if ( ! timer ) return false;
-
- timer->clearInterval();
- _intervalTimers[x] = NULL;
+ // will make sure next expire() will always return false!
+ timer.clearInterval();
assert(testInvariant());
@@ -441,10 +438,7 @@
it != itEnd;
++it)
{
- Timer* timerptr = *it;
- if ( ! timerptr ) continue;
-
- Timer& timer = *timerptr;
+ Timer& timer = *it;
if ( timer.expired() )
{
// log_msg("FIXME: Interval Timer Expired!\n");
Index: server/movie_root.h
===================================================================
RCS file: /sources/gnash/gnash/server/movie_root.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- server/movie_root.h 9 Feb 2007 05:52:49 -0000 1.35
+++ server/movie_root.h 9 Feb 2007 13:38:50 -0000 1.36
@@ -14,7 +14,7 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-/* $Id: movie_root.h,v 1.35 2007/02/09 05:52:49 rsavoye Exp $ */
+/* $Id: movie_root.h,v 1.36 2007/02/09 13:38:50 strk Exp $ */
/// \page events_handling Handling of user events
///
@@ -76,11 +76,10 @@
#include "mouse_button_state.h" // for composition
#include "drag_state.h" // for composition
#include "sprite_instance.h" // for inlines
+#include "timers.h" // for composition
// Forward declarations
-namespace gnash {
- class Timer;
-}
+// none needed
namespace gnash
{
@@ -204,10 +203,13 @@
/// Add an interval timer
//
+ /// @param timer
+ /// A Timer, will be copied.
+ ///
/// @return an integer indentifying the timer
/// for subsequent call to clear_interval_timer
///
- unsigned int add_interval_timer(Timer& timer);
+ unsigned int add_interval_timer(const Timer& timer);
/// Remove timer identified by given integer
//
@@ -389,7 +391,7 @@
// for timers, as we'll be removing them from the
// list but still want Timer "identifiers" to be
// valid.
- typedef std::vector<Timer *> TimerList;
+ typedef std::vector<Timer> TimerList;
TimerList _intervalTimers;
std::vector< as_object* > m_keypress_listeners;
Index: server/timers.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/timers.cpp,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- server/timers.cpp 9 Feb 2007 00:19:07 -0000 1.21
+++ server/timers.cpp 9 Feb 2007 13:38:50 -0000 1.22
@@ -18,7 +18,7 @@
//
//
-/* $Id: timers.cpp,v 1.21 2007/02/09 00:19:07 strk Exp $ */
+/* $Id: timers.cpp,v 1.22 2007/02/09 13:38:50 strk Exp $ */
#include "timers.h"
#include "as_function.h" // for class as_function
@@ -33,114 +33,70 @@
using namespace std;
namespace gnash {
+
Timer::Timer() :
- _which(0),
- _interval(0.0),
- _start(0.0),
+ _interval(0),
+ _start(0),
_object(0),
_env(0)
{
}
- Timer::Timer(as_value *obj, int ms)
- {
- setInterval(*obj, ms);
- start();
- }
-
Timer::~Timer()
{
- log_msg("%s: \n", __FUNCTION__);
- }
-
- int
- Timer::setInterval(as_value obj, int ms)
- {
- _function = obj;
- _interval = ms * 0.01;
- // _interval = ms * 0.000001;
- start();
-
- return 0;
- }
-
- int
- Timer::setInterval(as_value obj, int ms, as_environment *en)
- {
- _function = obj;
- _interval = ms * 0.01;
- _env = en;
- // _interval = ms * 0.000001;
- start();
-
- return 0;
+ //log_msg("%s: \n", __FUNCTION__);
}
- int
- Timer::setInterval(as_value obj, int ms, std::vector<variable *> *locals)
- {
- _function = obj;
- _interval = ms * 0.01;
- _locals = locals;
- // _interval = ms * 0.000001;
- start();
- return 0;
- }
- int
- Timer::setInterval(as_value obj, int ms, as_object *this_ptr, as_environment
*en)
+ void
+ Timer::setInterval(as_function& method, unsigned ms, as_object* this_ptr,
as_environment *env)
{
- _function = obj;
- _interval = ms * 0.01;
- _env = en;
+ _function = &method;
+ _interval = ms * 1000; // transform to microseconds
+ //log_msg("_interval microseconds: %lu", _interval);
+ _env = env;
_object = this_ptr;
- // _interval = ms * 0.000001;
start();
-
- return 0;
}
void
Timer::clearInterval()
{
- _interval = 0.0;
- _start = 0.0;
+ _interval = 0;
+ _start = 0;
}
void
Timer::start()
{
- uint64 ticks = tu_timer::get_profile_ticks();
- _start = tu_timer::profile_ticks_to_seconds(ticks);
+ _start = tu_timer::get_profile_ticks();
+ //log_msg("_start at seconds %lu", _start);
}
- bool
- Timer::expired()
+bool
+Timer::expired()
+{
+ if (_start)
{
- if (_start > 0.0) {
- uint64 ticks = tu_timer::get_profile_ticks();
- double now = tu_timer::profile_ticks_to_seconds(ticks);
+ uint64 now = tu_timer::get_profile_ticks();
+ //log_msg("now: %lu", now);
+ assert(now > _start);
+
//printf("FIXME: %s: now is %f, start time is %f, interval is %f\n",
__FUNCTION__, now, _start, _interval);
- if (now > _start + _interval) {
+ if (now > _start + _interval)
+ {
_start = now; // reset the timer
//log_msg("Timer expired! \n");
return true;
}
- // FIXME: Sometimes, "now" and "_start" have bad values.
- // I don't know why, but this works around the problem..
- else if (now < _start) {
- log_msg( "Timer::expired - now (%f) is before start (%f)!\n"
- " Expiring right now.\n",
- now, _start);
- _start = now;
- return true;
}
+ else
+ {
+ //log_msg("Timer not enabled!");
}
-
- // log_msg("Timer not enabled! \n");
return false;
- }
+}
void
Timer::operator() ()
@@ -148,26 +104,19 @@
//printf("FIXME: %s:\n", __FUNCTION__);
//log_msg("INTERVAL ID is %d\n", getIntervalID());
- const as_value& timer_method = getASFunction();
- as_environment* as_env = getASEnvironment();
-
- as_object* obj = getObject();
- as_value val = call_method(timer_method, as_env, obj, 0, 0);
-
- //as_object* this_ptr = getASObject();
- //as_value val = call_method(timer_method, as_env, this_ptr, 0, 0);
+ as_value timer_method(_function.get());
+ as_value val = call_method(timer_method, _env, _object.get(), 0, 0);
}
+// TODO: move to Global.cpp
void
timer_setinterval(const fn_call& fn)
{
- log_msg("%s: args=%d\n", __FUNCTION__, fn.nargs);
-
- timer_as_object *ptr = new timer_as_object;
+ //log_msg("%s: args=%d", __FUNCTION__, fn.nargs);
// Get interval function
- as_function *as_func = fn.arg(0).to_as_function();
+ boost::intrusive_ptr<as_function> as_func = fn.arg(0).to_as_function();
if ( ! as_func )
{
IF_VERBOSE_ASCODING_ERRORS(
@@ -183,44 +132,19 @@
// Get interval time
int ms = int(fn.arg(1).to_number());
- fn.env->add_frame_barrier();
- //method = env->get_variable("loopvar");
-
-#if 0
- // FIXME: This is pretty gross, but something is broke elsewhere and it
doesn't
- // seem to effect anything else. When a function is called from a executing
- // function, like calling setInterval() from within the callback to
- // XMLSocket::onConnect(), the local variables of the parent function need
to
- // be propogated to the local stack as regular variables (not locals) or
- // they can't be found in the scope of the executing chld function. There
is
- // probably a better way to do this... but at least this works.
- for (i=0; i< fn.env->get_local_frame_top(); i++) {
- if (fn.env->m_local_frames[i].m_name.size()) {
- //method = env->get_variable(env->m_local_frames[i].m_name);
- //if (method.get_type() != as_value::UNDEFINED)
- {
- string local_name = fn.env->m_local_frames[i].m_name;
- as_value local_val = fn.env->m_local_frames[i].m_value;
- fn.env->set_variable(local_name, local_val);
- }
- }
- }
-#endif
-
- as_value val(as_func);
-
- //Ptr->obj.setInterval(val, ms);
- ptr->obj.setInterval(val, ms, ptr, fn.env);
+ Timer timer;
+ timer.setInterval(*as_func, ms, fn.this_ptr, fn.env);
movie_root& root = VM::get().getRoot();
- int id = root.add_interval_timer(ptr->obj);
+ int id = root.add_interval_timer(timer);
fn.result->set_int(id);
}
+// TODO: move to Global.cpp
void
timer_clearinterval(const fn_call& fn)
{
- log_msg("%s: nargs = %d\n", __FUNCTION__, fn.nargs);
+ //log_msg("%s: nargs = %d", __FUNCTION__, fn.nargs);
int id = int(fn.arg(0).to_number());
@@ -228,4 +152,5 @@
bool ret = root.clear_interval_timer(id);
fn.result->set_bool(ret);
}
-}
+
+} // namespace gnash
Index: server/timers.h
===================================================================
RCS file: /sources/gnash/gnash/server/timers.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- server/timers.h 9 Feb 2007 00:19:07 -0000 1.13
+++ server/timers.h 9 Feb 2007 13:38:50 -0000 1.14
@@ -27,13 +27,17 @@
#include "as_value.h" // for struct variable composition
#include "as_object.h" // for inheritance
+#include "as_function.h" // for visibility of destructor by intrusive_ptr
+#include "smart_ptr.h"
#include "tu_timer.h"
#include <string>
+// Forward declarations
namespace gnash {
class fn_call;
+ class as_function;
}
namespace gnash {
@@ -43,62 +47,97 @@
as_value value;
};
- class Timer
- {
- public:
+/// An interval timer.
+//
+/// This is constructed when _global.setInterval() is called.
+/// Instances of this class will be stored in the movie_root singleton.
+///
+/// A timer has a function to call, a context in which to call it, and
+/// interval specifying how often the function must be called.
+//
+/// It is *not* a "smart" timer, which is
+/// it will *not* automatically execute at given intervals. Rather, it
+/// will be movie_root responsibility to execute the timer-associated
+/// function at regular intervals. As a facility, the Timer class provides
+/// an execution operator, proxying the execution to the associated function
+/// with properly set-up context.
+///
+///
+class Timer
+{
+
+public:
+
+ /// Construct a disabled (cleared) timer.
Timer();
- Timer(as_value *obj, int ms);
- Timer(as_value method, int ms);
+
~Timer();
- int setInterval(as_value obj, int ms);
- int setInterval(as_value obj, int ms, as_object *this_ptr,
as_environment *env);
- int setInterval(as_value obj, int ms, as_environment *env);
- int setInterval(as_value obj, int ms, std::vector<variable *> *locals);
- void setInterval(int ms)
- {
- _interval = ms * 0.000001;
- }
+ /// Setup the Timer, enabling it.
+ //
+ /// @param method
+ /// The function to call from execution operator.
+ /// Will be stored in an intrusive_ptr.
+ ///
+ /// @param ms
+ /// The number of milliseconds between expires.
+ ///
+ /// @param this_ptr
+ /// The object to be used as 'this' pointer when calling the
+ /// associated function. Will be stored in an intrusive_ptr.
+ /// It is allowed to be NULL as long as fn_call is allowed
+ /// a NULL as 'this_ptr' (we might want to change this).
+ ///
+ /// @param env
+ /// The environment in which the associated function will be run.
+ /// Not sure we should provide this rather then extracting from
this_ptr...
+ ///
+ void setInterval(as_function& method, unsigned ms, as_object* this_ptr,
as_environment *env);
+
+ /// Clear the timer, ready for reuse
+ //
+ /// When a Timer is cleared, the expired() function
+ /// will always return false.
+ ///
+ /// Use setInterval() to reset it.
+ ///
void clearInterval();
- void start();
- bool expired();
- void setObject(as_object *ao) { _object = ao; }
- as_object *getObject() { return _object; }
- // Accessors
- const as_value& getASFunction() { return _function; }
- as_environment *getASEnvironment() { return _env; }
- as_object *getASObject() { return _object; }
- std::vector<struct variable *> *getLocals() { return _locals; }
- int getIntervalID() { return _which; }
- void add_local(const std::string& name, as_value value) {
- struct variable *var = new struct variable; // FIXME: who'll delete ?
- var->name = name;
- var->value = value;
- _locals->push_back(var);
- }
+ /// Return true if interval ticks are passed since last call to start()
+ //
+ /// Always returns false if the timer is cleared.
+ //
+ bool expired();
- /// Execute timer function
+ /// Execute associated function properly setting up context
void operator() ();
- private:
- int _which; // Which timer
- double _interval;
- double _start;
- as_value _function;
- as_object *_object;
- as_environment *_env;
- std::vector<struct variable *> *_locals;
+private:
- };
+ /// Set timer start
+ //
+ /// Called by every function setting the interval.
+ ///
+ void start();
- class timer_as_object : public gnash::as_object
- {
- public:
- Timer obj;
- };
+ /// Number of microseconds between expirations
+ uint64 _interval;
+
+ /// Number of microseconds since epoch at Timer start
+ uint64 _start;
+
+ /// The associated function, stored in an intrusive pointer
+ boost::intrusive_ptr<as_function> _function;
+
+ /// Context for the function call. Will be used as 'this' pointer.
+ boost::intrusive_ptr<as_object> _object;
+
+ /// how to keep this alive ?
+ as_environment *_env;
+
+};
void timer_setinterval(const fn_call& fn);
void timer_clearinterval(const fn_call& fn);
Index: server/asobj/xmlsocket.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/xmlsocket.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/asobj/xmlsocket.cpp 9 Feb 2007 00:19:07 -0000 1.4
+++ server/asobj/xmlsocket.cpp 9 Feb 2007 13:38:50 -0000 1.5
@@ -26,6 +26,7 @@
#include "fn_call.h"
#include "sprite_instance.h"
#include "VM.h"
+#include "builtin_function.h" // for setting timer, should likely avoid that..
#include "log.h"
@@ -529,10 +530,9 @@
#if 1
Timer *timer = new Timer;
- as_c_function_ptr ondata_handler =
- (as_c_function_ptr)&xmlsocket_event_ondata;
- timer->setInterval(ondata_handler, 50, ptr, fn.env);
- timer->setObject(ptr);
+ boost::intrusive_ptr<builtin_function> ondata_handler = new builtin_function(
+ &xmlsocket_event_ondata, NULL);
+ timer->setInterval(*ondata_handler, 50, ptr, fn.env);
VM::get().getRoot().add_interval_timer(*timer);
#endif
Index: testsuite/misc-ming.all/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/Makefile.am,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -b -r1.62 -r1.63
--- testsuite/misc-ming.all/Makefile.am 8 Feb 2007 22:23:01 -0000 1.62
+++ testsuite/misc-ming.all/Makefile.am 9 Feb 2007 13:38:50 -0000 1.63
@@ -478,6 +478,9 @@
sh $< $(top_builddir) VarAndCharClashTest.swf > $@
chmod 755 $@
+intervalTest.swf: $(srcdir)/../media/green.swf ../Dejagnu.swf
$(srcdir)/intervalTest.as
+ $(MAKESWF) -o $@ ../Dejagnu.swf $(srcdir)/intervalTest.as
+
# This will only work with Ming-0.4.0beta2 (support for prebuilt clips
inclusion)
# Uses a low frame rate to test immediate redraw on key event
KeyTest.swf: $(srcdir)/../media/green.swf ../Dejagnu.swf $(srcdir)/KeyTest.as
Index: testsuite/misc-ming.all/intervalTest.as
===================================================================
RCS file: testsuite/misc-ming.all/intervalTest.as
diff -N testsuite/misc-ming.all/intervalTest.as
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/misc-ming.all/intervalTest.as 9 Feb 2007 13:38:50 -0000
1.1
@@ -0,0 +1,60 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+//
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+// These are already checked in Global.as, and it would be
+// clear if things don't work as expected
+check_equals(typeof(setInterval), 'function');
+check_equals(typeof(clearInterval), 'function');
+
+do_this = function() {
+ ++this_counter;
+ xtrace("Doing this "+this_counter);
+ if ( this_counter > 3 )
+ {
+ clearInterval(this_interval);
+ xtrace("This interval cleared ");
+ if ( this_counter > 4 )
+ {
+ totals();
+ }
+ }
+};
+
+do_that = function() {
+ ++that_counter;
+ xtrace("Doing that "+that_counter);
+ if ( that_counter > 3 )
+ {
+ clearInterval(that_interval);
+ xtrace("That interval cleared ");
+ this_interval = setInterval(do_this, 1);
+ // interval 1 is NOT reused
+ check_equals(this_interval, 3);
+ }
+};
+
+this_counter = 0;
+this_interval = setInterval(do_this, 0.0001);
+check_equals(this_interval, 1);
+
+that_counter = 0;
+that_interval = setInterval(do_that, 1000);
+check_equals(that_interval, 2);
+
+stop();