gnash-commit
[Top][All Lists]
Advanced

[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);
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]