From de040ceddd6d8ca837ae82ee658f6d45ecbb42f9 Mon Sep 17 00:00:00 2001
From: Sandro Santilli <strk@keybit.net>
Date: Sun, 31 Jul 2011 18:45:35 +0200
Subject: [PATCH] Add a way to wait for a given amount of bytes to be loaded

Use this to ensure 65535 bytes are loaded before constructing
an root movie. This fixes unstable results from the swfdec test
registerclass-previous.swf
---
 libcore/SWFMovie.cpp                  |    2 +
 libcore/parser/SWFMovieDefinition.cpp |   45 +++++++++++++++++++++++++++++++++
 libcore/parser/SWFMovieDefinition.h   |   20 +++++++++++---
 3 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/libcore/SWFMovie.cpp b/libcore/SWFMovie.cpp
index 64ce573..9b4e521 100644
--- a/libcore/SWFMovie.cpp
+++ b/libcore/SWFMovie.cpp
@@ -56,6 +56,8 @@ SWFMovie::construct(as_object* /*init*/)
         );
     }
 
+    _def->ensure_bytes_loaded(std::min<size_t>(65535, _def->get_bytes_total()));
+
     // Invoke parent placement event handler
     MovieClip::construct();  
 }
diff --git a/libcore/parser/SWFMovieDefinition.cpp b/libcore/parser/SWFMovieDefinition.cpp
index 84df363..5af3b20 100644
--- a/libcore/parser/SWFMovieDefinition.cpp
+++ b/libcore/parser/SWFMovieDefinition.cpp
@@ -155,6 +155,7 @@ SWFMovieDefinition::SWFMovieDefinition(const RunResources& runResources)
     _frames_loaded(0u),
     _waiting_for_frame(0),
     _bytes_loaded(0),
+    _waiting_for_bytes(0),
     m_loading_sound_stream(-1),
     m_file_length(0),
     m_jpeg_in(0),
@@ -394,6 +395,28 @@ SWFMovieDefinition::ensure_frame_loaded(size_t framenum) const
     return ( framenum <= _frames_loaded );
 }
 
+bool
+SWFMovieDefinition::ensure_bytes_loaded(size_t numbytes) const
+{
+    boost::mutex::scoped_lock lock(_bytes_loaded_mutex);
+
+#ifndef LOAD_MOVIES_IN_A_SEPARATE_THREAD
+    return ( numbytes <= _bytes_loaded );
+#endif
+
+    if ( numbytes <= _bytes_loaded ) return true;
+
+    // TODO: verify the parser is still alive before waiting
+    //       on a condition that will otherwise never arrive.
+
+    _waiting_for_bytes = numbytes;
+
+    // TODO: return false on timeout
+    _bytes_reached_condition.wait(lock);
+
+    return ( numbytes <= _bytes_loaded );
+}
+
 Movie*
 SWFMovieDefinition::createMovie(Global_as& gl, DisplayObject* parent)
 {
@@ -516,6 +539,12 @@ SWFMovieDefinition::read_all_swf()
         // Notify any thread waiting on frame reached condition
         _frame_reached_condition.notify_all();
     }
+
+    // Notify any thread waiting on bytes loaded condition
+    {
+        boost::mutex::scoped_lock lock(_bytes_loaded_mutex);
+        _bytes_reached_condition.notify_all();
+    }
 }
 
 size_t
@@ -559,6 +588,22 @@ SWFMovieDefinition::incrementLoadedFrames()
 }
 
 void
+SWFMovieDefinition:: setBytesLoaded(unsigned long bytes)
+{
+    boost::mutex::scoped_lock lock(_bytes_loaded_mutex);
+    _bytes_loaded=bytes;
+
+    // signal load of bytes if anyone requested it
+    if (_waiting_for_bytes && _bytes_loaded >= _waiting_for_bytes )
+    {
+        // or should we notify_one ?
+        // See: http://boost.org/doc/html/condition.html
+        _bytes_reached_condition.notify_all();
+    }
+
+}
+
+void
 SWFMovieDefinition::registerExport(const std::string& symbol,
         boost::uint16_t id)
 {
diff --git a/libcore/parser/SWFMovieDefinition.h b/libcore/parser/SWFMovieDefinition.h
index 510b2ef..d293a3d 100644
--- a/libcore/parser/SWFMovieDefinition.h
+++ b/libcore/parser/SWFMovieDefinition.h
@@ -338,6 +338,11 @@ public:
     /// has been loaded (load on demand).
     bool ensure_frame_loaded(size_t framenum) const;
 
+    /// \brief
+    /// Ensure that the given number of bytes 
+    /// has been loaded (load on demand).
+    bool ensure_bytes_loaded(size_t numbytes) const;
+
     /// Read and parse all the SWF stream (blocking until load is finished)
     //
     /// This function uses a private TagLoadersTable
@@ -481,6 +486,15 @@ private:
     /// thread will read it.
     mutable boost::mutex _bytes_loaded_mutex;
 
+    /// A semaphore to signal load of a minimum number of bytes
+    mutable boost::condition _bytes_reached_condition;
+
+    /// Set this to trigger signaling of reached amount of bytes loaded
+    //
+    /// Make sure you locked _bytes_loaded_mutex 
+    /// when accessing this member !
+    mutable size_t _waiting_for_bytes;
+
     int m_loading_sound_stream;
 
     boost::uint32_t m_file_length;
@@ -512,11 +526,7 @@ private:
     /// Set number of bytes loaded from input stream
     //
     /// NOTE: this method locks _bytes_loaded_mutex
-    void setBytesLoaded(unsigned long bytes)
-    {
-        boost::mutex::scoped_lock lock(_bytes_loaded_mutex);
-        _bytes_loaded=bytes;
-    }
+    void setBytesLoaded(unsigned long bytes);
 
     /// A flag set to true when load cancellation is requested
     bool _loadingCanceled;
-- 
1.7.0.4

