[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog server/asobj/LoadVars.cpp
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] gnash ChangeLog server/asobj/LoadVars.cpp |
Date: |
Sat, 24 Feb 2007 10:14:25 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Sandro Santilli <strk> 07/02/24 10:14:25
Modified files:
. : ChangeLog
server/asobj : LoadVars.cpp
Log message:
* server/asobj/LoadVars.cpp:
Made code more robust, and hopefully also cleaner.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2449&r2=1.2450
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/LoadVars.cpp?cvsroot=gnash&r1=1.8&r2=1.9
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2449
retrieving revision 1.2450
diff -u -b -r1.2449 -r1.2450
--- ChangeLog 23 Feb 2007 18:27:01 -0000 1.2449
+++ ChangeLog 24 Feb 2007 10:14:25 -0000 1.2450
@@ -1,3 +1,8 @@
+2007-02-24 Sandro Santilli <address@hidden>
+
+ * server/asobj/LoadVars.cpp:
+ Made code more robust, and hopefully also cleaner.
+
2007-02-23 Sandro Santilli <address@hidden>
* server/asobj/LoadVars.cpp:
Index: server/asobj/LoadVars.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/LoadVars.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- server/asobj/LoadVars.cpp 23 Feb 2007 18:29:10 -0000 1.8
+++ server/asobj/LoadVars.cpp 24 Feb 2007 10:14:25 -0000 1.9
@@ -55,8 +55,193 @@
//static as_object* getLoadVarsInterface();
//static void attachLoadVarsInterface(as_object& o);
-class LoadVarsLoader
+class LoadRequest
{
+public:
+ typedef map<string, string> ValuesMap;
+
+ LoadRequest(const URL& url)
+ :
+ _stream(StreamProvider::getDefaultInstance().getStream(url)),
+ _completed(false)
+ {
+ }
+
+ LoadRequest(const URL& url, const std::string& postdata)
+ :
+ _stream(StreamProvider::getDefaultInstance().getStream(url,
postdata)),
+ _completed(false)
+ {
+ }
+
+ LoadRequest(const LoadRequest& lr)
+ :
+ _stream(const_cast<LoadRequest&>(lr)._stream),
+ _completed(false)
+ {
+ }
+
+ ValuesMap& getValues()
+ {
+ return _vals;
+ }
+
+ void process()
+ {
+ assert(!_thread.get());
+ _thread.reset( new
boost::thread(boost::bind(LoadRequest::execLoadingThread, this)) );
+ }
+
+ bool inProgress()
+ {
+ return ( _thread.get() != NULL );
+ }
+
+ /// Mutex-protected inspector for thread completion
+ bool completed()
+ {
+ boost::mutex::scoped_lock lock(_mutex);
+ if ( _completed && _thread.get() )
+ {
+ _thread->join();
+ }
+ return _completed;
+ }
+
+ /// Mutex-protected mutator for thread completion
+ void setCompleted()
+ {
+ boost::mutex::scoped_lock lock(_mutex);
+ _completed = true;
+ _thread.reset();
+ }
+
+ /// Since I haven't found a way to pass boost::thread
+ /// constructor a non-static function, this is here to
+ /// workaround that limitation (in either boost or more
+ /// likely my own knowledge of it)
+ static void execLoadingThread(LoadRequest* ptr)
+ {
+ //log_msg("LoadVars loading thread started");
+ ptr->completeLoad();
+ //log_msg("LoadVars loading thread completed");
+ }
+
+ size_t getBytesLoaded() const {
+ return _bytesLoaded;
+ }
+
+ size_t getBytesTotal() const {
+ return _bytesTotal;
+ }
+
+
+private:
+
+ /// Load all data from the _stream input.
+ //
+ /// This function should be run by a separate thread.
+ ///
+ void completeLoad()
+ {
+ using std::string;
+
+ // TODO: how to set _bytesTotal ?
+
+ // this is going to override any previous setting,
+ // better do this inside a subclass (in a separate thread)
+ _bytesLoaded = 0;
+
+ //log_msg("completeLoad called");
+
+ string toparse;
+
+ size_t CHUNK_SIZE = 1024;
+ char buf[CHUNK_SIZE];
+ unsigned int parsedLines = 0;
+ while ( size_t read = _stream->read_bytes(buf, CHUNK_SIZE) )
+ {
+ // TODO: use read_string ?
+ string chunk(buf, read);
+ toparse += chunk;
+
+ //log_msg("toparse: %s", toparse.c_str());
+
+ // parse remainder
+ size_t lastamp = toparse.rfind('&');
+ if ( lastamp != string::npos )
+ {
+ string parseable = toparse.substr(0, lastamp);
+ //log_msg("parseable: %s", parseable.c_str());
+ parse(parseable);
+ //log_msg("Parsed %d vals", parsed);
+ toparse = toparse.substr(lastamp+1);
+ ++parsedLines;
+ }
+
+ _bytesLoaded += read;
+ //dispatchDataEvent();
+
+ // found newline, discard anything before that
+ if ( strchr(buf, '\n') )
+ {
+ if ( parsedLines ) break;
+ else toparse.clear();
+ }
+
+ // eof, get out !
+ if ( _stream->get_eof() ) break;
+ }
+
+ if ( ! toparse.empty() )
+ {
+ parse(toparse);
+ }
+
+ _stream->go_to_end();
+ _bytesLoaded = _stream->get_position();
+ _bytesTotal = _bytesLoaded;
+
+ //dispatchLoadEvent();
+
+ setCompleted();
+ }
+
+
+ /// Parse an url-encoded query string
+ //
+ /// Variables in the string will be added as properties
+ /// of this object.
+ ///
+ /// @param querystring
+ /// An url-encoded query string.
+ /// The string will be parsed using URL::parse_querystring
+ ///
+ /// @return the number of variables found in the string
+ ///
+ size_t parse(const std::string& str)
+ {
+ using std::map;
+ using std::string;
+
+ URL::parse_querystring(str, _vals);
+
+ return _vals.size();
+ }
+
+ size_t _bytesLoaded;
+
+ size_t _bytesTotal;
+
+ std::auto_ptr<tu_file> _stream;
+
+ std::auto_ptr<boost::thread> _thread;
+
+ ValuesMap _vals;
+
+ bool _completed;
+
+ boost::mutex _mutex;
};
/// LoadVars ActionScript class
@@ -114,62 +299,17 @@
/// new threads if needed.
void checkLoads();
- /// Process current load request
- //
- /// This function is called by addLoadRequest()
- /// if the just-added request is the only one in the queue
- /// and by endCurrentLoad() if any other request is
- /// in the queue.
- ///
- /// It will start a separate thread to process
- /// the request
- ///
- void processCurrentLoadRequest();
-
- /// Mark current load as done
- //
- /// This function removes the request from
- /// the _loadRequests list and resets the
- /// _currentLoad iterator.
- /// If _loadRequests is not empty, it processes
- /// the next request.
- ///
- void endCurrentLoad();
-
/// \brief
/// Add a load request to the queue, processing it
/// if no other loads are in progress.
///
- void addLoadRequest(const std::string& urlstr);
-
- /// Load all data from the _stream input.
- //
- /// This function should be run by a separate thread.
+ /// @param postdata
+ /// URL-encoded post data. NULL for no post.
///
- void completeLoad();
+ void addLoadRequest(const std::string& urlstr, const char*
postdata=NULL);
- /// Since I haven't found a way to pass boost::thread
- /// constructor a non-static function, this is here to
- /// workaround that limitation (in either boost or more
- /// likely my own knowledge of it)
- static void execCompleteLoad(LoadVars* lv) {
- //log_msg("LoadVars loading thread started");
- lv->completeLoad();
- //log_msg("LoadVars loading thread completed");
- }
-
- /// Parse an url-encoded query string
- //
- /// Variables in the string will be added as properties
- /// of this object.
- ///
- /// @param querystring
- /// An url-encoded query string.
- /// The string will be parsed using URL::parse_querystring
- ///
- /// @return the number of variables found in the string
- ///
- size_t parse(const std::string& querystring);
+ /// Process a completed load
+ size_t processLoaded(LoadRequest& lr);
/// Dispatch load event, if any
void dispatchLoadEvent();
@@ -214,7 +354,7 @@
size_t _bytesLoaded;
/// List of load requests
- typedef std::list<std::string> LoadRequests;
+ typedef std::list<LoadRequest> LoadRequests;
/// Load requests queue
//
@@ -234,8 +374,6 @@
std::auto_ptr<tu_file> _stream;
- mutable boost::mutex _loadRequestsMutex;
-
unsigned int _loadCheckerTimer;
};
@@ -259,20 +397,25 @@
void
LoadVars::checkLoads()
{
- // TODO: take care of setting members here,
- // we can't trust the loading thread to do so
- if ( _loadRequests.empty() )
+ /// Process a completed load if any
+ if ( isLoading() && _currentLoad->completed() )
{
- assert(_currentLoad == _loadRequests.end());
- // TODO: remove the timer, which would likely
- // destroy ourselves
- //log_msg("checkLoads(): no more requests, should shut down
timer");
- VM::get().getRoot().clear_interval_timer(_loadCheckerTimer);
+ processLoaded(*_currentLoad);
+ _loadRequests.pop_front();
+ _currentLoad = _loadRequests.end();
}
- else if ( _currentLoad == _loadRequests.end() )
+
+ if ( ! isLoading() )
+ {
+ if ( ! _loadRequests.empty() )
{
_currentLoad = _loadRequests.begin();
- processCurrentLoadRequest();
+ _currentLoad->process();
+ }
+ else
+ {
+
VM::get().getRoot().clear_interval_timer(_loadCheckerTimer);
+ }
}
}
@@ -341,16 +484,12 @@
/* private */
size_t
-LoadVars::parse(const std::string& str)
+LoadVars::processLoaded(LoadRequest& lr)
{
- using std::map;
+ typedef LoadRequest::ValuesMap ValuesMap;
using std::string;
- typedef map<string, string> ValuesMap;
-
- ValuesMap vals;
- URL::parse_querystring(str, vals);
-
+ ValuesMap& vals = lr.getValues();
for (ValuesMap::iterator it=vals.begin(), itEnd=vals.end();
it != itEnd; ++it)
{
@@ -358,108 +497,17 @@
//log_msg("Setting %s == %s", it->first.c_str(),
it->second.c_str());
}
- return vals.size();
-}
-
-/* private */
-void
-LoadVars::completeLoad()
-{
- using std::string;
-
- assert(isLoading());
-
- // TODO: how to set _bytesTotal ?
-
- // this is going to override any previous setting,
- // better do this inside a subclass (in a separate thread)
- _bytesLoaded = 0;
-
- //log_msg("completeLoad called");
-
- string toparse;
-
- size_t CHUNK_SIZE = 1024;
- char buf[CHUNK_SIZE];
- unsigned int parsedLines = 0;
- while ( size_t read = _stream->read_bytes(buf, CHUNK_SIZE) )
- {
- // TODO: use read_string ?
- string chunk(buf, read);
- toparse += chunk;
-
- //log_msg("toparse: %s", toparse.c_str());
-
- // parse remainder
- size_t lastamp = toparse.rfind('&');
- if ( lastamp != string::npos )
- {
- string parseable = toparse.substr(0, lastamp);
- //log_msg("parseable: %s", parseable.c_str());
- parse(parseable);
- //log_msg("Parsed %d vals", parsed);
- toparse = toparse.substr(lastamp+1);
- ++parsedLines;
- }
-
- _bytesLoaded += read;
- dispatchDataEvent();
-
- // found newline, discard anything before that
- if ( strchr(buf, '\n') )
- {
- if ( parsedLines ) break;
- else toparse.clear();
- }
-
- // eof, get out !
- if ( _stream->get_eof() ) break;
- }
-
- if ( ! toparse.empty() )
- {
- parse(toparse);
- }
-
- _stream->go_to_end();
- _bytesLoaded = _stream->get_position();
- _bytesTotal = _bytesLoaded;
+ _bytesLoaded = lr.getBytesLoaded();
+ _bytesTotal = lr.getBytesTotal();
dispatchLoadEvent();
- endCurrentLoad();
-}
-
-void
-LoadVars::endCurrentLoad()
-{
- boost::mutex::scoped_lock lock(_loadRequestsMutex);
- _loadRequests.erase(_currentLoad);
- _currentLoad = _loadRequests.end();
-}
-
-void
-LoadVars::processCurrentLoadRequest()
-{
-
- std::string& urlstr = *_currentLoad;
- StreamProvider& provider = StreamProvider::getDefaultInstance();
- URL url(urlstr, get_base_url());
-
- _stream.reset ( provider.getStream(url) );
-
- // WARNING: completeLoad must be called by a separate thread,
- // or we'll end up with a dead lock (completeLoad calls
- // endCurrentLoad and is called by it!)
- // When are we going to drop this ?
- boost::thread thread(boost::bind(LoadVars::execCompleteLoad, this));
+ return vals.size();
}
void
-LoadVars::addLoadRequest(const std::string& urlstr)
+LoadVars::addLoadRequest(const std::string& urlstr, const char* postdata)
{
- boost::mutex::scoped_lock lock(_loadRequestsMutex);
-
if ( _loadRequests.empty() )
{
//log_msg("addLoadRequest(): new requests, starting timer");
@@ -471,7 +519,12 @@
_loadCheckerTimer =
VM::get().getRoot().add_interval_timer(timer);
}
- _loadRequests.insert(_loadRequests.end(), urlstr);
+ URL url(urlstr, get_base_url());
+ if ( postdata ) {
+ _loadRequests.insert( _loadRequests.end(), LoadRequest(url,
postdata) );
+ } else {
+ _loadRequests.insert( _loadRequests.end(), LoadRequest(url) );
+ }
}
void