From: Braden M. <br...@us...> - 2006-11-22 00:05:22
|
Update of /cvsroot/openvrml/openvrml/src/libopenvrml/openvrml In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv3665/src/libopenvrml/openvrml Modified Files: browser.cpp browser.h Log Message: Factored creation of openvrml::resource_istreams to a dedicated abstract factory, openvrml::resource_fetcher. This allows the code associated with resource fetching to live at least as long as the browser instance, which it needs to do if there are any outstanding fetches happening when the browser instance is destroyed. Index: browser.cpp =================================================================== RCS file: /cvsroot/openvrml/openvrml/src/libopenvrml/openvrml/browser.cpp,v retrieving revision 1.194 retrieving revision 1.195 diff -C2 -d -r1.194 -r1.195 *** browser.cpp 17 Nov 2006 06:47:25 -0000 1.194 --- browser.cpp 22 Nov 2006 00:05:18 -0000 1.195 *************** *** 4591,4594 **** --- 4591,4748 ---- /** + * @class openvrml::resource_fetcher + * + * @brief An abstract factory for @c resource_istream%s. + * + * A concrete implementation of this interface must be passed to + * <code>browser</code>'s constructor. + * + * @sa openvrml::browser + */ + + /** + * @brief Destroy. + */ + openvrml::resource_fetcher::~resource_fetcher() OPENVRML_NOTHROW + {} + + /** + * @brief Fetch a network resource. + * + * @param[in] uri a Uniform Resource Identifier. + * + * This function delegates to @c resource_fetcher::do_get_resource. + * + * @return the requested resource as a stream. + */ + std::auto_ptr<openvrml::resource_istream> + openvrml::resource_fetcher::get_resource(const std::string & uri) + { + return this->do_get_resource(uri); + } + + /** + * @fn std::auto_ptr<openvrml::resource_istream> openvrml::resource_fetcher::do_get_resource(const std::string & uri) + * + * @brief Fetch a network resource. + * + * Called by @c resource_fetcher::get_resource, clients of OpenVRML are + * required to provide an implementation for this function. OpenVRML depends + * on the implementation of this function for all of its input needs. As + * such, what kind of resources OpenVRML is capable of resolving is entirely + * dependent on code provided by the application. A trivial implementation + * designed to handle only @c file resources can use @c std::filebuf: + * + * @code + * std::auto_ptr<openvrml::resource_istream> + * my_resource_fetcher::do_get_resource(const std::string & uri) + * { + * using std::auto_ptr; + * using std::invalid_argument; + * using std::string; + * using openvrml::resource_istream; + * + * class file_resource_istream : public resource_istream { + * std::string url_; + * std::filebuf buf_; + * + * public: + * explicit file_resource_istream(const std::string & path): + * resource_istream(&this->buf_) + * { + * // + * // Note that the failbit is set in the constructor if no data + * // can be read from the stream. This is important. If the + * // failbit is not set on such a stream, OpenVRML will attempt + * // to read data from a stream that cannot provide it. + * // + * if (!this->buf_.open(path.c_str(), ios_base::in)) { + * this->setstate(ios_base::failbit); + * } + * } + * + * void url(const std::string & str) + * { + * this->url_ = str; + * } + * + * private: + * virtual const std::string url() const + * { + * return this->url_; + * } + * + * virtual const std::string type() const + * { + * // + * // A real application should use OS facilities for this; + * // however, that is beyond the scope of this example (which + * // is intended to be portable and stupid). + * // + * using std::find; + * using std::string; + * using boost::algorithm::iequals; + * using boost::next; + * string media_type = "application/octet-stream"; + * const string::const_reverse_iterator dot_pos = + * find(this->url_.rbegin(), this->url_.rend(), '.'); + * if (dot_pos == this->url_.rend() + * || next(dot_pos.base()) == this->url_.end()) { + * return media_type; + * } + * const string::const_iterator hash_pos = + * find(next(dot_pos.base()), this->url_.end(), '#'); + * const string ext(dot_pos.base(), hash_pos); + * if (iequals(ext, "wrl")) { + * media_type = "model/vrml"; + * } else if (iequals(ext, "png")) { + * media_type = "image/png"; + * } else if (iequals(ext, "jpg") || iequals(ext, "jpeg")) { + * media_type = "image/jpeg"; + * } + * return media_type; + * } + * + * virtual bool data_available() const + * { + * return !!(*this); + * } + * }; + * + * const string scheme = uri.substr(0, uri.find_first_of(':')); + * if (scheme != "file") { + * throw invalid_argument('\"' + scheme + "\" URI scheme not " + * "supported"); + * } + * // + * // file:// + * // ^ + * // 01234567 + * // + * string path = uri.substr(uri.find_first_of('/', 7)); + * + * auto_ptr<resource_istream> in(new file_resource_istream(path)); + * static_cast<file_resource_istream *>(in.get())->url(uri); + * + * return in; + * } + * @endcode + * + * The @p uri parameter is provided by OpenVRML and can be assumed to be an + * absolute URI. As such, it will always have a scheme through which the + * client code can choose a resolution mechanism. For more information on URI + * syntax, see <a + * href="ftp://ftp.rfc-editor.org/in-notes/std/std66.txt">Internet + * STD 66</a>. + * + * @param[in] uri an absolute Uniform Resource Identifier. + * + * @return the requested resource as a stream. + * + * @sa ftp://ftp.rfc-editor.org/in-notes/std/std66.txt + */ + + + /** * @class openvrml::stream_listener * *************** *** 4909,4915 **** * @brief Encapsulates a VRML browser. * ! * @c browser is the foundation of the OpenVRML runtime. Users need to ! * inherit this class and override @c browser::do_get_resource and provide an ! * implementation of @c resource_istream. */ --- 5063,5077 ---- * @brief Encapsulates a VRML browser. * ! * @c browser is the foundation of the OpenVRML runtime. @c browser is ! * instantiated with an implementation of @c resource_fetcher, which is ! * provided by application code. The @c resource_fetcher instance must have a ! * longer lifetime than the @c browser instance, since the @c resource_fetcher ! * instance could be used during destruction of the @c browser. Note, ! * however, that <code>browser</code>'s destructor will block until all ! * threads that may use the @c resource_fetcher have completed. So it is ! * sufficient to have the @c browser and the @c resource_fetcher destroyed ! * sequentially in the same thread. ! * ! * @sa openvrml::resource_fetcher */ *************** *** 5464,5473 **** * @brief Constructor. * ! * @param[in] out output stream for console output. ! * @param[in] err output stream for error console output. * * @exception std::bad_alloc if memory allocation fails. */ ! openvrml::browser::browser(std::ostream & out, std::ostream & err) OPENVRML_THROW1(std::bad_alloc): null_node_metatype_(new null_node_metatype(*this)), --- 5626,5638 ---- * @brief Constructor. * ! * @param[in] fetcher a @c resource_fetcher implementation. ! * @param[in] out output stream for console output. ! * @param[in] err output stream for error console output. * * @exception std::bad_alloc if memory allocation fails. */ ! openvrml::browser::browser(resource_fetcher & fetcher, ! std::ostream & out, ! std::ostream & err) OPENVRML_THROW1(std::bad_alloc): null_node_metatype_(new null_node_metatype(*this)), *************** *** 5484,5487 **** --- 5649,5653 ---- viewer_(0), modified_(false), + fetcher_(fetcher), out_(&out), err_(&err), *************** *** 5780,5917 **** /** - * @brief Fetch a network resource. - * - * @param[in] uri a Uniform Resource Identifier. - * - * @return the requested resource as a stream. - */ - std::auto_ptr<openvrml::resource_istream> - openvrml::browser::get_resource(const std::string & uri) - { - return this->do_get_resource(uri); - } - - /** - * @fn std::auto_ptr<openvrml::resource_istream> openvrml::browser::do_get_resource(const std::string & uri) - * - * @brief Fetch a network resource. - * - * Called by @c browser::get_resource, clients of OpenVRML are required to - * provide an implementation for this function. OpenVRML depends on the - * implementation of this function for all of its input needs. As such, what - * kind of resources OpenVRML is capable of resolving is entirely dependent on - * code provided by the application. A trivial implementation designed to - * handle only @c file resources can use @c std::filebuf: - * - * @code - * std::auto_ptr<openvrml::resource_istream> - * my_browser::do_get_resource(const std::string & uri) - * { - * using std::auto_ptr; - * using std::invalid_argument; - * using std::string; - * using openvrml::resource_istream; - * - * class file_resource_istream : public resource_istream { - * std::string url_; - * std::filebuf buf_; - * - * public: - * explicit file_resource_istream(const std::string & path): - * resource_istream(&this->buf_) - * { - * // - * // Note that the failbit is set in the constructor if no data - * // can be read from the stream. This is important. If the - * // failbit is not set on such a stream, OpenVRML will attempt - * // to read data from a stream that cannot provide it. - * // - * if (!this->buf_.open(path.c_str(), ios_base::in)) { - * this->setstate(ios_base::failbit); - * } - * } - * - * void url(const std::string & str) - * { - * this->url_ = str; - * } - * - * private: - * virtual const std::string url() const - * { - * return this->url_; - * } - * - * virtual const std::string type() const - * { - * // - * // A real application should use OS facilities for this; - * // however, that is beyond the scope of this example (which - * // is intended to be portable and stupid). - * // - * using std::find; - * using std::string; - * using boost::algorithm::iequals; - * using boost::next; - * string media_type = "application/octet-stream"; - * const string::const_reverse_iterator dot_pos = - * find(this->url_.rbegin(), this->url_.rend(), '.'); - * if (dot_pos == this->url_.rend() - * || next(dot_pos.base()) == this->url_.end()) { - * return media_type; - * } - * const string::const_iterator hash_pos = - * find(next(dot_pos.base()), this->url_.end(), '#'); - * const string ext(dot_pos.base(), hash_pos); - * if (iequals(ext, "wrl")) { - * media_type = "model/vrml"; - * } else if (iequals(ext, "png")) { - * media_type = "image/png"; - * } else if (iequals(ext, "jpg") || iequals(ext, "jpeg")) { - * media_type = "image/jpeg"; - * } - * return media_type; - * } - * - * virtual bool data_available() const - * { - * return !!(*this); - * } - * }; - * - * const string scheme = uri.substr(0, uri.find_first_of(':')); - * if (scheme != "file") { - * throw invalid_argument('\"' + scheme + "\" URI scheme not " - * "supported"); - * } - * // - * // file:// - * // ^ - * // 01234567 - * // - * string path = uri.substr(uri.find_first_of('/', 7)); - * - * auto_ptr<resource_istream> in(new file_resource_istream(path)); - * static_cast<file_resource_istream *>(in.get())->url(uri); - * - * return in; - * } - * @endcode - * - * The @p uri parameter is provided by OpenVRML and can be assumed to be an - * absolute URI. As such, it will always have a scheme through which the - * client code can choose a resolution mechanism. For more information on URI - * syntax, see <a - * href="ftp://ftp.rfc-editor.org/in-notes/std/std66.txt">Internet - * STD 66</a>. - * - * @param[in] uri an absolute Uniform Resource Identifier. - * - * @return the requested resource as a stream. - * - * @sa ftp://ftp.rfc-editor.org/in-notes/std/std66.txt - */ - - /** * @brief Get the browser name. * --- 5946,5949 ---- *************** *** 7200,7204 **** try { ! in = this->browser().get_resource(absolute_uri); } catch (...) { throw unreachable_url(); --- 7232,7236 ---- try { ! in = this->browser().fetcher_.get_resource(absolute_uri); } catch (...) { throw unreachable_url(); Index: browser.h =================================================================== RCS file: /cvsroot/openvrml/openvrml/src/libopenvrml/openvrml/browser.h,v retrieving revision 1.61 retrieving revision 1.62 diff -C2 -d -r1.61 -r1.62 *** browser.h 28 Jul 2006 07:04:19 -0000 1.61 --- browser.h 22 Nov 2006 00:05:18 -0000 1.62 *************** *** 53,56 **** --- 53,68 ---- + class OPENVRML_API resource_fetcher { + public: + virtual ~resource_fetcher() OPENVRML_NOTHROW = 0; + + std::auto_ptr<resource_istream> get_resource(const std::string & uri); + + private: + virtual std::auto_ptr<resource_istream> + do_get_resource(const std::string & uri) = 0; + }; + + class OPENVRML_API stream_listener { public: *************** *** 171,174 **** --- 183,187 ---- class OPENVRML_API browser : boost::noncopyable { + friend class scene; friend class Vrml97Parser; friend class X3DVrmlParser; *************** *** 241,244 **** --- 254,259 ---- mutable boost::mutex modified_mutex_; + resource_fetcher & fetcher_; + mutable boost::mutex out_mutex_; std::ostream * const out_; *************** *** 255,259 **** bool flags_need_updating; ! browser(std::ostream & out, std::ostream & err) OPENVRML_THROW1(std::bad_alloc); virtual ~browser() OPENVRML_NOTHROW; --- 270,276 ---- bool flags_need_updating; ! browser(resource_fetcher & fetcher, ! std::ostream & out, ! std::ostream & err) OPENVRML_THROW1(std::bad_alloc); virtual ~browser() OPENVRML_NOTHROW; *************** *** 284,288 **** void viewer(openvrml::viewer * v) OPENVRML_THROW1(viewer_in_use); openvrml::viewer * viewer() const OPENVRML_NOTHROW; - std::auto_ptr<resource_istream> get_resource(const std::string & uri); virtual const char * name() const OPENVRML_NOTHROW; --- 301,304 ---- *************** *** 341,348 **** protected: bool headlight_on(); - - private: - virtual std::auto_ptr<resource_istream> - do_get_resource(const std::string & uri) = 0; }; --- 357,360 ---- |