gnomemm r1679 - in gstreamermm/trunk: . gstreamer/src tests
- From: jaalburqu svn gnome org
- To: svn-commits-list gnome org
- Subject: gnomemm r1679 - in gstreamermm/trunk: . gstreamer/src tests
- Date: Mon, 11 Aug 2008 04:37:08 +0000 (UTC)
Author: jaalburqu
Date: Mon Aug 11 04:37:08 2008
New Revision: 1679
URL: http://svn.gnome.org/viewvc/gnomemm?rev=1679&view=rev
Log:
2008-08-11 Josà Alburquerque <jaalburqu svn gnome org>
* gstreamer/src/iterator.ccg:
* gstreamer/src/iterator.hg: Removed ConcurrentUpdateException and
used std::runtime_error with description for iterator concurrent
update. Renamed is_last() to is_end() (logic was flawed on what
Gst::ITERATOR_DONE means -- one past last element, not *on* last
element). Added Gst::IteratorBasic (for non reference counted
objects) and made Gst::Iterator derive from it. Added (questionable?)
operator->() to Gst::Iterator.
* tests/test-iterator.cc: Rewrote test.
Modified:
gstreamermm/trunk/ChangeLog
gstreamermm/trunk/gstreamer/src/iterator.ccg
gstreamermm/trunk/gstreamer/src/iterator.hg
gstreamermm/trunk/tests/test-iterator.cc
Modified: gstreamermm/trunk/gstreamer/src/iterator.ccg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/iterator.ccg (original)
+++ gstreamermm/trunk/gstreamer/src/iterator.ccg Mon Aug 11 04:37:08 2008
@@ -20,17 +20,3 @@
*/
#include <gst/gstenumtypes.h>
-
-namespace Gst
-{
-
-ConcurrentUpdateException::ConcurrentUpdateException()
-: std::runtime_error(what())
-{}
-
-const char* ConcurrentUpdateException::what() const throw()
-{
- return "Concurrent update of iterator elements. Please resync iterator.";
-}
-
-} //namespace Gst
Modified: gstreamermm/trunk/gstreamer/src/iterator.hg
==============================================================================
--- gstreamermm/trunk/gstreamer/src/iterator.hg (original)
+++ gstreamermm/trunk/gstreamer/src/iterator.hg Mon Aug 11 04:37:08 2008
@@ -30,21 +30,14 @@
_WRAP_ENUM(IteratorItem, GstIteratorItem)
_WRAP_ENUM(IteratorResult, GstIteratorResult)
-/** Exception thrown by Gst::IteratorBase<> increment operators when the
- * elements are updated after element processing is underway by the iterator.
- */
-class ConcurrentUpdateException : std::runtime_error
-{
-public:
- ConcurrentUpdateException();
- virtual const char* what() const throw();
-};
-
/** Gst::IteratorBase â Base class for classes that retrieve multiple elements
* in a thread safe way.
*
* Classes derived from Gst::IteratorBase are used to retrieve multiple objects
- * from another object in a thread safe way.
+ * from another object in a thread safe way. They are implemented as C++ like
+ * input iterators so they do not support multi-passing, but they are usable
+ * enough for iterating through a list of items and referencing them in a
+ * single pass.
*
* Various GStreamer objects provide access to their internal structures using
* an iterator.
@@ -53,38 +46,34 @@
class IteratorBase
{
public:
- /** Frees the underlying C instance if a destroy value of true was used to
- * wrap it.
- */
- virtual ~IteratorBase();
-
- /** Move to the next iterator item.
+ /** Moves to the next iterator item.
*
- * @return The result of the iteration. Please note that a return of
- * Gst::ITERATOR_DONE means that the iterator is on the last item. MT safe.
+ * @return The result of the iteration. MT safe.
*/
- IteratorResult next();
+ virtual IteratorResult next();
- /** Resync the iterator. This function is mostly called after next() returns
- * Gst::ITERATOR_RESYNC. In essence, the iterator is reset to the first item
- * because a concurrent update of the iterator's list of element occurred
- * while element processing was underway which means a call to this method is
- * necessary.
+ /** Resynchronize the iterator. This function is mostly called after next()
+ * returns Gst::ITERATOR_RESYNC. A result of Gst::ITERATOR_RESYNC from
+ * next() means that a concurrent update was made to the iterator list during
+ * iteration and the iterator needs to be resynchronized before continuing.
+ * Use this function to resynchronize.
*/
void resync();
- /** Tells if iterator is at start of list (not on first item, but just
- * before it).
+ /** Tells if the iterator is at the start of the list (not on the first item,
+ * but just before it). Increment the iterator or use
+ * Gst::IteratorBasic::begin() to go to the first item.
*
- * @return true if iterator is at start of list, false otherwise.
+ * @return true if the iterator is at the start of the list, false otherwise.
*/
bool is_start() const;
- /** Tells if iterator is on the last element.
+ /** Tells if the iterator is at the end of the list (just after the last
+ * element).
*
- * @return true if iterator is at end of list, false otherwise.
+ * @return true if the iterator is at the end of the list, false otherwise.
*/
- bool is_last() const;
+ bool is_end() const;
/** Tells whether the iterator is valid and can be dereferenced.
*/
@@ -96,6 +85,11 @@
///Provides access to the underlying C GObject.
const GstIterator* cobj() const { return cobject_; };
+ /** Frees the underlying C instance if a destroy value of true was used to
+ * wrap it.
+ */
+ virtual ~IteratorBase();
+
protected:
/// Default constructor.
IteratorBase();
@@ -107,14 +101,14 @@
*/
IteratorBase(const IteratorBase<CppType>&);
- /** Construct an IteratorBase from an underlying C object.
+ /** Constructs an IteratorBase from an underlying C object.
* @param castitem The underlying C object.
- * @param destroy Whether to destroy underlying C object along with the
+ * @param destroy Whether to destroy the underlying C object along with the
* wrapper.
*/
IteratorBase(GstIterator* castitem, bool destroy=true);
- /** Assignment operator. It replaces the contents of this iterator with the
+ /** Assignment operator. It replaces the contents of the iterator with the
* contents of the new one freeing the underlying C object if a destroy value
* of true was used when wrapping it. Please note that copying and assigning
* merely shares the underlying C object. Operations on the copy are also
@@ -138,17 +132,74 @@
void swap(IteratorBase<CppType>& other);
};
-/** Gst::Iterator â Class that retrieve multiple elements in a thread safe way.
+/** Gst::IteratorBasic â Class that retrieves multiple elements in a thread
+ * safe way.
+ * Gst::IteratorBasic iterates specifically through elements that are not
+ * reference counted. Though it is mostly not used, it is included for
+ * completeness. Gst::Iterator, which iterates through reference counted
+ * objects is mostly used for iterating through objects because the ones that
+ * are iterated in GStreamer are mostly reference counted.
+ */
+template <class CppType>
+class IteratorBasic : public IteratorBase<CppType>
+{
+public:
+ ///Default constructor.
+ IteratorBasic();
+
+ /** Creates a Gst::IteratorBasic wrapper for a GstIterator object. The
+ * underlying @a castitem will be freed with the Gst::IteratorBasic
+ * destruction if a destroy value of true is given.
+ *
+ * @param castitem The C instance to wrap.
+ * @param destroy Whether to destroy the underlying C object with the
+ * wrapper.
+ */
+ IteratorBasic(GstIterator* castitem, bool destroy=true);
+
+ /** Resynchronizes the iterator and moves the iterator to the first item.
+ *
+ * @throw std::runtime_error (if a Gst::ITERATOR_ERROR is encountered or if a
+ * concurrent update to the iterator occurs while it is advanced to the first
+ * element).
+ */
+ void begin();
+
+ /** Dereferences the iterator and obtains the underlying object.
+ */
+ CppType operator*() const;
+
+ /** Prefix auto-increment operator. It advances to the next item in the
+ * iterator. It is faster than the postfix operator.
+ * @throw std::runtime_error (if a Gst::ITERATOR_ERROR is encountered or if a
+ * concurrent update to the iterator occurs while it iterates).
+ */
+ IteratorBasic<CppType>& operator++();
+
+ /** Postfix auto-increment operator. It advances to the next item in the
+ * iterator.
+ * @throw std::runtime_error (if a Gst::ITERATOR_ERROR is encountered or if a
+ * concurrent update to the iterator occurs while it iterates).
+ */
+ IteratorBasic<CppType> operator++(int);
+};
+
+/** Gst::Iterator â Class that retrieve multiple reference counted elements in
+ * a thread safe way.
* Gst::Iterator iterates specifically through elements that are reference
* counted and therefore dereferencing the elements of the iterator yields a
* Glib::RefPtr<> to the C++ element type.
*/
template <class CppType>
-class Iterator : public IteratorBase<CppType>
+class Iterator : public IteratorBasic<CppType>
{
public:
+ ///Default constructor.
+ Iterator();
+
/** Creates a Gst::Iterator wrapper for a GstIterator object. The underlying
- * @a castitem will be freed with the Gst::Iterator destruction.
+ * @a castitem will be freed with the Gst::Iterator destruction if a destroy
+ * value of true is given.
*
* @param castitem The C instance to wrap.
* @param destroy Whether to destroy the underlying C object with the
@@ -156,21 +207,32 @@
*/
Iterator(GstIterator* castitem, bool destroy=true);
- /** Dereference this iterator and obtain the underlying Glib::RefPtr<>.
+ /** Moves to the next iterator item.
+ *
+ * @return The result of the iteration. MT safe.
+ */
+ IteratorResult next();
+
+ /** Dereferences the iterator and obtains the underlying Glib::RefPtr<>.
*/
Glib::RefPtr<CppType> operator*() const;
+ //TODO: Should this operator be included?
+ /** Accesses underlying object member through the RefPtr<>.
+ */
+ CppType* operator->() const;
+
/** Prefix auto-increment operator. It advances to the next item in the
* iterator. It is faster than the postfix operator.
- * @throw Gst::ConcurrentUpdateException.
- * @throw std::runtime_error (when Gst::ITERATOR_ERROR is encountered).
+ * @throw std::runtime_error (if a Gst::ITERATOR_ERROR is encountered or if a
+ * concurrent update to the iterator occurs while it iterates).
*/
Iterator<CppType>& operator++();
/** Postfix auto-increment operator. It advances to the next item in the
* iterator.
- * @throw Gst::ConcurrentUpdateException.
- * @throw std::runtime_error (when Gst::ITERATOR_ERROR is encountered).
+ * @throw std::runtime_error (if a Gst::ITERATOR_ERROR is encountered or if a
+ * concurrent update to the iterator occurs while it iterates).
*/
Iterator<CppType> operator++(int);
};
@@ -183,6 +245,11 @@
IteratorResult IteratorBase<CppType>::next()
{
current_result = (Gst::IteratorResult) gst_iterator_next(cobj(), ¤t);
+
+ // Set current to NULL if iterator is done:
+ if (current_result == Gst::ITERATOR_DONE)
+ current = 0;
+
return current_result;
}
@@ -201,9 +268,9 @@
}
template<class CppType>
-bool IteratorBase<CppType>::is_last() const
+bool IteratorBase<CppType>::is_end() const
{
- return (current != 0 && current_result == Gst::ITERATOR_DONE);
+ return (current_result == Gst::ITERATOR_DONE);
}
template<class CppType>
@@ -274,34 +341,116 @@
}
}
-/******************* Gst::Iterator<CppType> **************************/
+/***************** Gst::IteratorBasic<CppType> ***********************/
template <class CppType>
-Iterator<CppType>::Iterator(GstIterator* castitem, bool destroy)
+IteratorBasic<CppType>::IteratorBasic()
+ : IteratorBase<CppType>()
+{}
+
+template <class CppType>
+IteratorBasic<CppType>::IteratorBasic(GstIterator* castitem, bool destroy)
: IteratorBase<CppType>(castitem, destroy)
{}
+template<class CppType>
+void IteratorBasic<CppType>::begin()
+{
+ this->resync();
+ ++(*this);
+}
+
template <class CppType>
-Glib::RefPtr<CppType> Iterator<CppType>::operator*() const
+CppType IteratorBasic<CppType>::operator*() const
{
typedef typename CppType::BaseObjectType CType;
if (this->current)
return Glib::wrap((CType*)(this->current));
else
- return Glib::RefPtr<CppType>(0);
+ return CppType();
}
template<class CppType>
-Iterator<CppType>& Iterator<CppType>::operator++()
+IteratorBasic<CppType>& IteratorBasic<CppType>::operator++()
{
const IteratorResult result = this->next();
if (result == Gst::ITERATOR_RESYNC)
- throw ConcurrentUpdateException();
+ throw std::runtime_error("Concurrent update of iterator elements. Please resync.");
else if (result == Gst::ITERATOR_ERROR)
- throw std::runtime_error("Iterator increment error.");
+ throw std::runtime_error("Iterator error while incrementing.");
+
+ return *this;
+}
+
+template<class CppType>
+IteratorBasic<CppType> IteratorBasic<CppType>::operator++(int)
+{
+ IteratorBasic<CppType> original = *this;
+ ++(*this);
+ return original;
+}
+
+/******************* Gst::Iterator<CppType> **************************/
+
+template <class CppType>
+Iterator<CppType>::Iterator()
+ : IteratorBasic<CppType>()
+{}
+
+template <class CppType>
+Iterator<CppType>::Iterator(GstIterator* castitem, bool destroy)
+ : IteratorBasic<CppType>(castitem, destroy)
+{}
+
+template <class CppType>
+IteratorResult Iterator<CppType>::next()
+{
+ const IteratorResult result = IteratorBasic<CppType>::next();
+ // Remove extra reference that gst_iterator_next() takes because references
+ // are taken when using Gst::Iterator<CppType> dereferencing operators (* and
+ // ->).
+ if (this->current)
+ g_object_unref(this->current);
+
+ return result;
+}
+
+template <class CppType>
+Glib::RefPtr<CppType> Iterator<CppType>::operator*() const
+{
+ typedef typename CppType::BaseObjectType CType;
+
+ if (this->current)
+ {
+ //Take extra reference when dereferencing. The reference will disappear
+ //when Glib::RefPtr<> is destroyed.
+ return Glib::wrap((CType*)(this->current), true);
+ }
+ else
+ return Glib::RefPtr<CppType>(0);
+}
+
+template <class CppType>
+CppType* Iterator<CppType>::operator->() const
+{
+ typedef typename CppType::BaseObjectType CType;
+
+ if (this->current)
+ {
+ //Take extra reference when dereferencing. The reference will disappear
+ //when Glib::RefPtr<> is destroyed.
+ return Glib::wrap((CType*)(this->current), true).operator->();
+ }
+ else
+ return (CppType*) 0;
+}
+template<class CppType>
+Iterator<CppType>& Iterator<CppType>::operator++()
+{
+ IteratorBasic<CppType>::operator++();
return *this;
}
Modified: gstreamermm/trunk/tests/test-iterator.cc
==============================================================================
--- gstreamermm/trunk/tests/test-iterator.cc (original)
+++ gstreamermm/trunk/tests/test-iterator.cc Mon Aug 11 04:37:08 2008
@@ -28,44 +28,53 @@
Glib::RefPtr<Gst::Pipeline> pipeline;
Glib::RefPtr<Gst::Bin> bin;
- Glib::RefPtr<Gst::Element> source, sink;
+ Glib::RefPtr<Gst::Element> e1, e2, e3, e4;
pipeline = Gst::Pipeline::create("my-pipeline");
bin = Gst::Bin::create("my-bin");
- source = Gst::ElementFactory::create_element("fakesrc", "source");
- sink = Gst::ElementFactory::create_element("fakesink", "sink");
+ e1 = Gst::ElementFactory::create_element("fakesrc", "element1");
+ e2 = Gst::ElementFactory::create_element("fakesrc", "element2");
+ e3 = Gst::ElementFactory::create_element("fakesrc", "element3");
+ e4 = Gst::ElementFactory::create_element("fakesink", "element4");
- bin->add(source)->add(sink);
+ bin->add(e1)->add(e2)->add(e3)->add(e4);
pipeline->add(bin);
- source->link(sink);
std::cout << "The following elements have been added to bin '" <<
bin->get_name() << "'." << std::endl;
int iterations = 0;
Gst::Iterator<Gst::Element> elements = bin->iterate_elements();
+ Gst::Iterator<Gst::Element> firstIter;
try
{
- for ( ; !elements.is_last(); ++elements)
+ for (elements.begin(); !elements.is_end(); ++elements, ++iterations)
{
- if (elements)
- std::cout << (*elements)->get_name() << std::endl;
+ if (!firstIter)
+ firstIter = elements;
- iterations++;
+ std::cout << elements->get_name() << std::endl;
}
- ++elements;
+
+ if (firstIter)
+ std::cout << "The first element iterator processed is '" <<
+ firstIter->get_name() << "'." << std::endl;
+
+ if (elements)
+ std::cout << "elements.is_end() == true && (elements) is valid." <<
+ std::endl;
}
catch (std::runtime_error& e)
{
std::cout << "Runtime error while iterating through \"" <<
- bin->get_name() << "'s\" elements." << std::endl;
+ bin->get_name() << "'s\" elements:" << std::endl << e.what() << std::endl;
}
- std::cout << "The loop iterated " << iterations << " to print bin '" <<
- bin->get_name() << "' elements." << std::endl;
+ std::cout << "The loop iterated " << iterations <<
+ " time(s) to print bin '" << bin->get_name() << "' elements." << std::endl;
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]