[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog server/asobj/xml.cpp server/aso...
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] gnash ChangeLog server/asobj/xml.cpp server/aso... |
Date: |
Thu, 20 Dec 2007 22:37:13 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Sandro Santilli <strk> 07/12/20 22:37:13
Modified files:
. : ChangeLog
server/asobj : xml.cpp xml.h
testsuite/actionscript.all: XML.as
Log message:
Load XML in background threads, fix abort on myXML.load() calls.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5231&r2=1.5232
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xml.cpp?cvsroot=gnash&r1=1.57&r2=1.58
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xml.h?cvsroot=gnash&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/XML.as?cvsroot=gnash&r1=1.49&r2=1.50
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.5231
retrieving revision 1.5232
diff -u -b -r1.5231 -r1.5232
--- ChangeLog 20 Dec 2007 22:31:31 -0000 1.5231
+++ ChangeLog 20 Dec 2007 22:37:12 -0000 1.5232
@@ -1,5 +1,9 @@
2007-12-20 Sandro Santilli <address@hidden>
+ * server/asobj/xml.{cpp,h}: don't abort on XML.load() [ no args ].
+ Engage a thread for each load request.
+ * testsuite/actionscript.all/XML.as: the test is now sane, and
+ have few more successes.
* libbase/LoadThread.{cpp,h}: (setupCache) fix current position
and _completed computation, (reset) join thread.
Index: server/asobj/xml.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/xml.cpp,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -b -r1.57 -r1.58
--- server/asobj/xml.cpp 17 Dec 2007 22:57:18 -0000 1.57
+++ server/asobj/xml.cpp 20 Dec 2007 22:37:13 -0000 1.58
@@ -17,7 +17,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/* $Id: xml.cpp,v 1.57 2007/12/17 22:57:18 strk Exp $ */
+/* $Id: xml.cpp,v 1.58 2007/12/20 22:37:13 strk Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -65,10 +65,6 @@
static void attachXMLInterface(as_object& o);
static void attachXMLProperties(as_object& o);
-// Callback functions for xmlReadIO
-static int closeTuFile (void * context);
-static int readFromTuFile (void * context, char * buffer, int len);
-
DSOEXPORT as_value xml_new(const fn_call& fn);
static as_value xml_load(const fn_call& fn);
static as_value xml_addrequestheader(const fn_call& fn);
@@ -81,7 +77,6 @@
static as_value xml_sendandload(const fn_call& fn);
static as_value xml_ondata(const fn_call& fn);
-static LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
#ifdef USE_DEBUGGER
static Debugger& debugger = Debugger::getDefaultInstance();
#endif
@@ -89,10 +84,12 @@
XML::XML()
:
XMLNode(getXMLInterface()),
+ _doc(0),
+ _firstChild(0),
_loaded(-1),
- _bytes_loaded(0),
- _bytes_total(0),
- _status(sOK)
+ _status(sOK),
+ _loadThreads(),
+ _loadCheckerTimer(0)
{
//GNASH_REPORT_FUNCTION;
#ifdef DEBUG_MEMORY_ALLOCATION
@@ -107,10 +104,12 @@
XML::XML(const std::string& xml_in)
:
XMLNode(getXMLInterface()),
+ _doc(0),
+ _firstChild(0),
_loaded(-1),
- _bytes_loaded(0),
- _bytes_total(0),
- _status(sOK)
+ _status(sOK),
+ _loadThreads(),
+ _loadCheckerTimer(0)
{
//GNASH_REPORT_FUNCTION;
#ifdef DEBUG_MEMORY_ALLOCATION
@@ -119,21 +118,6 @@
parseXML(xml_in);
}
-XML::XML(struct node * /* childNode */)
- :
- XMLNode(getXMLInterface()),
- _loaded(-1),
- _bytes_loaded(0),
- _bytes_total(0),
- _status(sOK)
-{
- GNASH_REPORT_FUNCTION;
-#ifdef DEBUG_MEMORY_ALLOCATION
- log_msg(_("\tCreating XML data at %p"), this);
-#endif
- //log_msg("%s: %p", __FUNCTION__, this);
-}
-
bool
XML::get_member(string_table::key name, as_value *val, string_table::key
nsname)
{
@@ -185,6 +169,11 @@
{
//GNASH_REPORT_FUNCTION;
+ for (LoadThreadList::iterator it=_loadThreads.begin(); it !=
_loadThreads.end(); ++it)
+ {
+ delete *it; // supposedly joins the thread
+ }
+
#ifdef DEBUG_MEMORY_ALLOCATION
log_msg(_("\tDeleting XML top level node at %p"), this);
#endif
@@ -407,35 +396,116 @@
GNASH_REPORT_FUNCTION;
// Set the "loaded" parameter to false
- VM& vm = _vm;
+ VM& vm = getVM();
string_table& st = vm.getStringTable();
string_table::key loadedKey = st.find("loaded");
- string_table::key onDataKey = st.find(PROPNAME("onData"));
set_member(loadedKey, as_value(false));
- // TODO:
- // 1. interrupt any pre-existing loading thread (send onLoad event in that
case?)
- // 2. start new loading thread
- //
- // Using LoadThread should do. Most likely we should do something
- // similar for LoadVars or ::loadVariables, so might consider generalizing
- // a load-in-a-separate-thread-calling-onLoad-when-done class
- //
- // The class would use a separate thread, provide cancelling and
- // will call a specified function (or functor) when all data arrived,
- // passing it the full data buffer.
+ bool startTimer = _loadThreads.empty();
+
+ std::auto_ptr<LoadThread> lt ( new LoadThread );
+ lt->setStream(str);
+
+ // we push on the front to avoid invalidating
+ // iterators when queueLoad is called as effect
+ // of onData invocation.
+ // Doing so also avoids processing queued load
+ // request immediately
//
- std::string src;
- char buf[256];
- log_debug("Started loading of XML in main tread... ");
- while ( 1 )
- {
- size_t bytes = str->read_bytes(buf, 255);
- src.append(buf, bytes);
- if ( bytes < 255 ) break; // end of buffer
+ _loadThreads.push_front(lt.get());
+ log_debug("Pushed thread %p to _loadThreads, number of XML load threads
now: " SIZET_FMT, (void*)lt.get(), _loadThreads.size());
+ lt.release();
+
+
+ if ( startTimer )
+ {
+ boost::intrusive_ptr<builtin_function> loadsChecker = \
+ new builtin_function(&XML::checkLoads_wrapper);
+ std::auto_ptr<Timer> timer(new Timer);
+ timer->setInterval(*loadsChecker, 50, this);
+ _loadCheckerTimer = getVM().getRoot().add_interval_timer(timer, true);
+ log_debug("Registered XML loads interval %d", _loadCheckerTimer);
+ }
+
+}
+
+size_t
+XML::getBytesLoaded() const
+{
+ if ( _loadThreads.empty() ) return 0;
+ LoadThread* lt = _loadThreads.front();
+ return lt->getBytesLoaded();
+}
+
+size_t
+XML::getBytesTotal() const
+{
+ if ( _loadThreads.empty() ) return 0;
+ LoadThread* lt = _loadThreads.front();
+ return lt->getBytesTotal();
+}
+
+/* private */
+void
+XML::checkLoads()
+{
+ static int call=0;
+ log_debug("XML %p checkLoads call %d, _loadThreads: %d", (void *)this,
_loadThreads.size(), ++call);
+
+ if ( _loadThreads.empty() ) return; // nothing to do
+
+ VM& vm = getVM();
+ string_table& st = vm.getStringTable();
+ string_table::key onDataKey = st.find(PROPNAME("onData"));
+
+ for (LoadThreadList::iterator it=_loadThreads.begin();
+ it != _loadThreads.end(); )
+ {
+ LoadThread* lt = *it;
+
+ // TODO: notify progress
+
+ log_debug("XML loads thread %p got %ld/%ld bytes", (void*)lt,
lt->getBytesLoaded(), lt->getBytesTotal() );
+ if ( lt->completed() )
+ {
+ size_t xmlsize = lt->getBytesTotal();
+ boost::scoped_array<char> buf(new char[xmlsize+1]);
+ size_t actuallyRead = lt->read(buf.get(), xmlsize);
+ assert(actuallyRead = xmlsize);
+ buf[xmlsize] = '\0';
+ as_value dataVal(buf.get()); // memory copy here (optimize?)
+
+ it = _loadThreads.erase(it);
+ delete lt; // supposedly joins the thread...
+
+ // might push_front on the list..
+ callMethod(onDataKey, dataVal);
+
+ log_debug("Completed load, _loadThreads have now " SIZET_FMT "
elements", _loadThreads.size());
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ if ( _loadThreads.empty() )
+ {
+ log_debug("Clearing XML load checker interval timer");
+ vm.getRoot().clear_interval_timer(_loadCheckerTimer);
+ _loadCheckerTimer=0;
}
- log_debug("... finished loading of XML in main tread.");
- callMethod(onDataKey, as_value(src));
+}
+
+/* private static */
+as_value
+XML::checkLoads_wrapper(const fn_call& fn)
+{
+ log_debug("checkLoads_wrapper called");
+
+ boost::intrusive_ptr<XML> ptr = ensureType<XML>(fn.this_ptr);
+ ptr->checkLoads();
+ return as_value();
}
// This reads in an XML file from disk and parses into into a memory resident
@@ -451,9 +521,10 @@
if ( ! str.get() )
{
log_error(_("Can't load XML file: %s (security?)"), url.str().c_str());
- as_value nullValue; nullValue.set_null();
- callMethod(VM::get().getStringTable().find("onData"), nullValue);
return false;
+ // TODO: this is still not correct.. we should still send onData
later...
+ //as_value nullValue; nullValue.set_null();
+ //callMethod(VM::get().getStringTable().find(PROPNAME("onData")),
nullValue);
}
log_msg(_("Loading XML file from url: '%s'"), url.str().c_str());
@@ -535,6 +606,14 @@
boost::intrusive_ptr<XML> xml_obj = ensureType<XML>(fn.this_ptr);
+ if ( ! fn.nargs )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("XML.load(): missing argument"));
+ );
+ return rv;
+ }
+
const std::string& filespec = fn.arg(0).to_string();
URL url(filespec, get_base_url());
@@ -834,26 +913,6 @@
}
-// Callback function for xmlReadIO
-static int
-readFromTuFile (void * context, char * buffer, int len)
-{
- tu_file* str = static_cast<tu_file*>(context);
- size_t read = str->read_bytes(buffer, len);
- if ( str->get_error() ) return -1;
- else return read;
-}
-
-// Callback function for xmlReadIO
-static int
-closeTuFile (void * /*context*/)
-{
- // nothing to do, the tu_file destructor will close
- //tu_file* str = static_cast<tu_file*>(context);
- //str->close();
- return 0; // no error
-}
-
#if 0 // not time for this (yet)
static
void _xmlErrorHandler(void* ctx, const char* fmt, ...)
Index: server/asobj/xml.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/xml.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- server/asobj/xml.h 20 Nov 2007 12:04:56 -0000 1.22
+++ server/asobj/xml.h 20 Dec 2007 22:37:13 -0000 1.23
@@ -26,22 +26,19 @@
#include "event_id.h"
#include "action.h"
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-#include <vector>
-#include <sstream>
-
+#include "LoadThread.h"
#include "xmlattrs.h"
#include "xmlnode.h"
+#include "log.h"
-#ifdef DEBUG_MEMORY_ALLOCATION
- #include "log.h"
-#endif
-
+#include <vector>
+#include <sstream>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xmlreader.h>
+//#define DEBUG_MEMORY_ALLOCATION 1
+
using namespace std;
namespace gnash {
@@ -49,6 +46,7 @@
// Forward declarations
class fn_call;
class URL;
+class LoaderThread;
/// XML class and ActionScript object
class DSOLOCAL XML : public XMLNode
@@ -92,8 +90,7 @@
XML();
XML(const std::string& xml_in);
- XML(struct node * childNode);
- virtual ~XML();
+ ~XML();
/// This is overridden to provide the 'status' and 'loaded' members,
/// which are NOT proper properties !
@@ -138,13 +135,11 @@
// the XML object was successfully
// loaded with XML.load() or
// XML.sendAndLoad().
-
bool loaded() { return _loaded; }
XMLNode *processNode(xmlTextReaderPtr reader, XMLNode *node);
void change_stack_frame(int frame, gnash::as_object *xml,
gnash::as_environment *env);
-// void setupStackFrames(gnash::as_object *xml, gnash::as_environment
*env);
void cleanupStackFrames( XMLNode *data);
@@ -163,8 +158,8 @@
void sendAndLoad();
- int getBytesLoaded() { return _bytes_loaded; };
- int getBytesTotal() { return _bytes_total; };
+ size_t getBytesLoaded() const;
+ size_t getBytesTotal() const;
private:
@@ -199,10 +194,6 @@
// 1 if successfully loaded
int _loaded;
- size_t _bytes_loaded;
-
- size_t _bytes_total;
-
Status _status;
/// Trigger the onLoad event, if any
@@ -230,6 +221,22 @@
void queueLoad(std::auto_ptr<tu_file> str);
//static void _xmlErrorHandler(void *ctx, const char* fmt, ...);
+
+ typedef std::list<LoadThread*> LoadThreadList;
+
+ /// Queue of load requests
+ LoadThreadList _loadThreads;
+
+ /// The load checker interval timer used to make loads async
+ unsigned int _loadCheckerTimer;
+
+ /// Wrapper around checkLoads for use as a Timer
+ /// interval for checking loads
+ static as_value checkLoads_wrapper(const fn_call& fn);
+
+ /// Scan the LoadThread queue (_loadThreads) to see if any of
+ /// them completed. If any did, invoke the onData event
+ void checkLoads();
};
Index: testsuite/actionscript.all/XML.as
===================================================================
RCS file: /sources/gnash/gnash/testsuite/actionscript.all/XML.as,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -b -r1.49 -r1.50
--- testsuite/actionscript.all/XML.as 20 Dec 2007 17:49:57 -0000 1.49
+++ testsuite/actionscript.all/XML.as 20 Dec 2007 22:37:13 -0000 1.50
@@ -20,7 +20,7 @@
// compile this test case with Ming makeswf, and then
// execute it like this gnash -1 -r 0 -v out.swf
-rcsid="$Id: XML.as,v 1.49 2007/12/20 17:49:57 strk Exp $";
+rcsid="$Id: XML.as,v 1.50 2007/12/20 22:37:13 strk Exp $";
#include "check.as"
//#include "dejagnu.as"
@@ -712,7 +712,7 @@
if ( this.onLoadCalls == 2 )
{
#if OUTPUT_VERSION < 6
- xcheck_totals(262);
+ check_totals(262);
#else
xcheck_totals(337);
#endif
@@ -741,9 +741,9 @@
#else // OUTPUT_VERSION >= 7
check_equals(typeof(myxml.LOADED), 'undefined');
#endif // OUTPUT_VERSION >= 7
-xcheck(! myxml.loaded ); // is really loaded in a background thread
+check(! myxml.loaded ); // is really loaded in a background thread
-xcheck_equals(myxml.loaded, false ); // is really loaded in a background thread
+check_equals(myxml.loaded, false ); // is really loaded in a background thread
note("myxml.loaded = "+myxml.loaded);
note("myxml.load() returned "+ret);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash ChangeLog server/asobj/xml.cpp server/aso...,
Sandro Santilli <=