1 /* gstreamermm - a C++ wrapper for gstreamer
2  *
3  * Copyright 2014 The gstreamermm Development Team
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 #ifndef _GSTREAMERMM_ATOMICQUEUE_H
21 #define _GSTREAMERMM_ATOMICQUEUE_H
22 
23 #include <glibmm/refptr.h>
24 #include <gstreamermm/handle_error.h>
25 #include <gst/gstatomicqueue.h>
26 
27 namespace Gst
28 {
29 
30 /**
31  * The Gst::AtomicQueue object implements a queue that can be used from multiple
32  * threads without performing any blocking operations.
33  */
34 template <typename T>
35 class AtomicQueue
36 {
37   public:
38 #ifndef DOXYGEN_SHOULD_SKIP_THIS
39   typedef AtomicQueue CppObjectType;
40   typedef GstAtomicQueue BaseObjectType;
41 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
42 
43 
44   /** Increment the reference count for this object.
45    * You should never need to do this manually - use the object via a RefPtr instead.
46    */
reference()47   void reference()   const
48   {
49     // See the comment at the top of this file, if you want to know why the cast works.
50     gst_atomic_queue_ref(reinterpret_cast<GstAtomicQueue*>(const_cast<AtomicQueue<T>*>(this)));
51   }
52 
53   /** Decrement the reference count for this object.
54    * You should never need to do this manually - use the object via a RefPtr instead.
55    */
unreference()56   void unreference() const
57   {
58     // See the comment at the top of this file, if you want to know why the cast works.
59     gst_atomic_queue_unref(reinterpret_cast<GstAtomicQueue*>(const_cast<AtomicQueue<T>*>(this)));
60   }
61 
62   ///Provides access to the underlying C instance.
gobj()63   const GstAtomicQueue* gobj() const
64   {
65     // See the comment at the top of this file, if you want to know why the cast works.
66     return reinterpret_cast<const GstAtomicQueue*>(this);
67   }
68 
69   ///Provides access to the underlying C instance.
gobj()70   GstAtomicQueue*       gobj()
71   {
72     // See the comment at the top of this file, if you want to know why the cast works.
73     return reinterpret_cast<GstAtomicQueue*>(this);
74   }
75 
76   ///Provides access to the underlying C instance. The caller is responsible for unrefing it. Use when directly setting fields in structs.
gobj_copy()77   GstAtomicQueue* gobj_copy() const
78   {
79     // See the comment at the top of this file, if you want to know why the cast works.
80     GstAtomicQueue *const gobject = reinterpret_cast<GstAtomicQueue*>(const_cast<AtomicQueue<T>*>(this));
81     gst_atomic_queue_ref(gobject);
82     return gobject;
83   }
84 
create(guint initial_size)85   static Glib::RefPtr<Gst::AtomicQueue<T> > create(guint initial_size)
86   {
87     // See the comment at the top of this file, if you want to know why the cast works.
88     return Glib::RefPtr<AtomicQueue<T> >(reinterpret_cast<AtomicQueue<T>*>(gst_atomic_queue_new(initial_size)));
89   }
90 
91 protected:
92   // Do not derive this.  Gst::AtomicQueue can neither be constructed nor deleted.
93   AtomicQueue();
94   void operator delete(void*, std::size_t);
95 
96 private:
97   // noncopyable
98   AtomicQueue(const AtomicQueue&);
99   AtomicQueue& operator=(const AtomicQueue&);
100 
101 
102 public:
103 
104   /** Get the amount of items in the queue.
105    * @return The number of elements in the queue.
106    */
length()107   guint length()
108   {
109     return gst_atomic_queue_length(gobj());
110   }
111 
112   /** Get the amount of items in the queue.
113    * @return The number of elements in the queue.
114    */
length()115   guint length() const
116   {
117 	  return const_cast<AtomicQueue*>(this)->length();
118   }
119 
120   /** Append @a data to the tail of the queue.
121    * @param data The data.
122    */
push(const T & data)123   void push(const T& data)
124   {
125     T* tmp = new T(data);
126     gst_atomic_queue_push(gobj(), tmp);
127   }
128 
129   /** Peek the head element of the queue without removing it from the queue.
130    * @return The head element of queue.
131    *
132    * @throws std::runtime_error if the queue is empty.
133    */
peek()134   T peek()
135   {
136     gpointer val = gst_atomic_queue_peek(gobj());
137     if (val == nullptr)
138       gstreamermm_handle_error("Queue is empty");
139     T v = *(T*)val;
140     return v;
141   }
142 
143   /** Get the head element of the queue.
144    * @return The head element of queue.
145    *
146    * @throws std::runtime_error if the queue is empty.
147    */
pop()148   T pop()
149   {
150     gpointer val = gst_atomic_queue_pop(gobj());
151     if (val == nullptr)
152       gstreamermm_handle_error("Queue is empty");
153     T v = *(T*)val;
154     delete (T*)val;
155     return v;
156   }
157 
158 };
159 
160 } // namespace Gst
161 
162 
163 namespace Glib
164 {
165 
166   /** A Glib::wrap() method for this object.
167    *
168    * @param object The C instance.
169    * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
170    * @result A C++ instance that wraps this C instance.
171    *
172    * @relates Gst::AtomicQueue
173    */
174   template <typename T>
175   Glib::RefPtr<Gst::AtomicQueue<T> > wrap(GstAtomicQueue* object, bool take_copy = false)
176   {
177     if(take_copy && object)
178       gst_atomic_queue_ref(object);
179     // See the comment at the top of this file, if you want to know why the cast works.
180     return Glib::RefPtr<Gst::AtomicQueue<T> >(reinterpret_cast<Gst::AtomicQueue<T>*>(object));
181   }
182 
183 } // namespace Glib
184 
185 
186 #endif /* _GSTREAMERMM_ATOMICQUEUE_H */
187 
188