1 Conventions for thread a safe API
2 ---------------------------------
4 The GStreamer API is designed to be thread safe. This means that API functions
5 can be called from multiple threads at the same time. GStreamer internally uses
6 threads to perform the data passing and various asynchronous services such as
7 the clock can also use threads.
9 This design decision has implication for the usage of the API and the objects
10 which this document explains.
15 Several design patterns are used to guarantee object consistency in GStreamer.
16 This is an overview of the methods used in various GStreamer subsystems.
20 All shared objects have a refcount associated with them. Each reference
21 obtained to the object should increase the refcount and each reference lost
22 should decrease the refcount.
24 The refcounting is used to make sure that when another thread destroys the
25 object, the ones which still hold a reference to the object do not read from
26 invalid memory when accessing the object.
28 Refcounting is also used to ensure that mutable data structures are only
29 modified when they are owned by the calling code.
31 It is a requirement that when two threads have a handle on an object, the
32 refcount must be more than one. This means that when one thread passes an
33 object to another thread it must increase the refcount. This requirement makes
34 sure that one thread cannot suddenly dispose the object making the other
35 thread crash when it tries to access the pointer to invalid memory.
37 Shared data structures and writability:
39 All objects have a refcount associated with them. Each reference obtained to
40 the object should increase the refcount and each reference lost should
41 decrease the refcount.
43 Each thread having a refcount to the object can safely read from the object.
44 but modifications made to the object should be preceeded with a
45 _get_writable() function call. This function will check the refcount of the
46 object and if the object is referenced by more than one instance, a copy is
47 made of the object that is then by definition only referenced from the calling
48 thread. This new copy is then modifyable without being visible to other
51 This technique is used for information objects that, once created, never
52 change their values. The lifetime of these objects is generally short, the
53 objects are usually simple and cheap to copy/create.
55 The advantage of this method is that no reader/writers locks are needed. all
56 threads can concurrently read but writes happen locally on a new copy. In most
57 cases _get_writable() can avoid a real copy because the calling method is the
58 only one holding a reference, wich makes read/writes very cheap.
60 The drawback is that sometimes 1 needless copy can be done. This would happen
61 when N threads call _get_writable() at the same time, all seeing that N
62 references are held on the object. In this case 1 copy too many will be done.
63 This is not a problem in any practical situation because the copy operation is
66 Mutable substructures:
68 Special techniques are necessary to ensure the consistency of compound shared
69 objects. As mentioned above, shared objects need to have a reference count of
70 1 if they are to be modified. Implicit in this assumption is that all parts of
71 the shared object belong only to the object. For example, a GstStructure in
72 one GstCaps object should not belong to any other GstCaps object. This
73 condition suggests a parent-child relationship: structures can only be added
74 to parent object if they do not already have a parent object.
76 In addition, these substructures must not be modified while more than one code
77 segment has a reference on the parent object. For example, if the user creates
78 a GstStructure, adds it to a GstCaps, and the GstCaps is then referenced by
79 other code segments, the GstStructure should then become immutable, so that
80 changes to that data structure do not affect other parts of the code. This
81 means that the child is only mutable when the parent's reference count is 1,
82 as well as when the child structure has no parent.
84 The general solution to this problem is to include a field in child structures
85 pointing to the parent's atomic reference count. When set to NULL, this
86 indicates that the child has no parent. Otherwise, procedures that modify the
87 child structure must check if the parent's refcount is 1, and otherwise must
88 cause an error to be signaled.
90 Note that this is an internal implementation detail; application or plugin
91 code that calls _get_writable() on an object is guaranteed to receive an
92 object of refcount 1, which must then be writable. The only trick is that a
93 pointer to a child structure of an object is only valid while the calling code
94 has a reference on the parent object, because the parent is the owner of the
99 For objects that contain state information and generally have a longer
100 lifetime, object locking is used to update the information contained in the
103 All readers and writers acquire the lock before accessing the object. Only one
104 thread is allowed access the protected structures at a time.
106 Object locking is used for all objects extending from GstObject such as
111 Atomic operations are operations that are performed as one consistent
112 operation even when executed by multiple threads. They do however not use the
113 conventional aproach of using mutexes to protect the critical section but rely
114 on CPU features and instructions.
116 The advantages are mostly speed related since there are no heavyweight locks
117 involved. Most of this instructions also do not cause a context switch in case
118 of concurrent access but use a retry mechanism or spinlocking.
120 Disadvantages are that each of these instructions usually cause a cache flush
121 on multi-CPU machines when two processors perform concurrent access.
123 Atomic operations are generally used for refcounting and for the allocation of
124 small fixed size objects in a memchunk. They can also be used to implement a
125 lockfree list or stack.
133 - atomic operations for refcounting
136 All objects should have a lock associated with them. This lock is used to keep
137 internal consistency when multiple threads call API function on the object.
139 For objects that extend the GStreamer base object class this lock can be
140 obtained with the macros GST_LOCK() and GST_UNLOCK(). For other object that do
141 not extend from the base GstObject class these macros can be different.
145 All new objects created have the FLOATING flag set. This means that the object
146 is not owned or managed yet by anybody other than the one holding a reference
147 to the object. The object in this state has a reference count of 1.
149 Various object methods can take ownership of another object, this means that
150 after calling a method on object A with an object B as an argument, the object
151 B is made sole property of object A. This means that after the method call you
152 are not allowed to access the object anymore unless you keep an extra
153 reference to the object. An example of such a method is the _bin_add() method.
154 As soon as this function is called in a Bin, the element passed as an argument
155 is owned by the bin and you are not allowed to access it anymore without
156 taking a _ref() before adding it to the bin. The reason being that after the
157 _bin_add() call disposing the bin also destroys the element.
159 Taking ownership of an object happens trough the process of "sinking" the
160 object. the _sink() method on an object will decrease the refcount of the
161 object if the FLOATING flag is set. The act of taking ownership of an object
162 is then performed as a _ref() followed by a _sink() call on the object.
164 The float/sink process is very useful when initializing elements that will
165 then be placed under control of a parent. The floating ref keeps the object
166 alive until it is parented, and once the object is parented you can forget
169 * parent-child relations
171 One can create parent-child relationships with the _object_set_parent()
172 method. This method refs and sinks the object and assigns its parent property
173 to that of the managing parent.
175 The child is said to have a weak link to the parent since the refcount of the
176 parent is not increased in this process. This means that if the parent is
177 disposed it has to unset itself as the parent of the object before disposing
178 itself, else the child object holds a parent pointer to invalid memory.
180 The responsibilites for an object that sinks other objects are summarised as:
182 - taking ownership of the object
183 - call _object_set_parent() to set itself as the object parent, this call
184 will _ref() and _sink() the object.
185 - keep reference to object in a datastructure such as a list or array.
188 - call _object_unparent() to reset the parent property and unref the
190 - remove the object from the list.
195 Most objects also expose state information with public properties in the
196 object. Two types of properties might exist: accessible with or without
197 holding the object lock. All properties should only be accessed with their
198 corresponding macros. The public object properties are marked in the .h files
199 with /*< public >*/. The public properties that require a lock to be held are
200 marked with /*< public >*/ /* with <lock_type> */, where <lock_type> can be
201 "LOCK" or "STATE_LOCK" or any other lock to mark the type(s) of lock to be
206 in GstPad there is a public property "direction". It can be found in the
207 section marked as public and requiring the LOCK to be held. There exists
208 also a macro to access the property.
212 /*< public >*/ /* with LOCK */
214 GstPadDirection direction;
218 #define GST_RPAD_DIRECTION(pad) (GST_REAL_PAD_CAST(pad)->direction)
220 Accessing the property is therefore allowed with the following code example:
223 direction = GST_RPAD_DIRECTION (pad);
228 All properties requiring a lock can change after releasing the associated
229 lock. This means that as long as you hold the lock, the state of the
230 object regarding the locked properties is consistent with the information
231 obtained. As soon as the lock is released, any values required from the
232 properties might not be valid anymore and can as best be described as a
233 snapshot of the state when the lock was held.
235 This means that all properties that require access beyond the scope of the
236 critial section should be copied or refcounted before releasing the lock.
238 Most object provide a _get_<property>() method to get a copy or refcounted
239 instance of the property value. The caller should not wory about any locks
240 but should unref/free the object after usage.
244 the following example correctly gets the peer pad of an element. It is
245 required to increase the refcount of the peer pad because as soon as the
246 lock is released, the peer could be unreffed and disposed, making the
247 pointer obtained in the critical section point to invalid memory.
250 peer = GST_RPAD_PEER (pad);
252 gst_object_ref (GST_OBJECT (peer));
257 gst_object_unref (GST_OBJECT (peer));
259 Note that after releasing the lock the peer might not actually be the peer
260 anymore of the pad. If you need to be sure it is, you need to extend the
261 critical section to include the operations on the peer.
265 Accessing the name of an object makes a copy of the name. The caller of the
266 function should g_free() the name after usage.
269 name = g_strdup (object->name);
278 For aplications it is encouraged to use the public methods of the object. Most
279 useful operations can be performed with the methods so it is seldom required
280 to access the public fields manually.
282 All accessor methods that return an object should increase the refcount of the
283 returned object. The caller should _unref() the object after usage. Each
284 method should state this refcounting policy in the documentation.
288 If the object property is a list, concurrent list iteration is needed to get
289 the contents of the list. GStreamer uses the cookie mechanism to mark the last
290 update of a list. The list and the cookie are protected by the same lock. Each
291 update to a list requires the following actions:
298 Updating the cookie is usually done by incrementing its value by one. Since
299 cookies use guint32 its wraparound is for all practical reasons is not a
302 Iterating a list can safely be done by surrounding the list iteration with a
303 lock/unlock of the lock.
305 In some cases it is not a good idea to hold the lock for a long time while
306 iterating the list. The state change code for a bin in GStreamer, for example,
307 has to iterate over each element and perform a blocking call on each of them
308 causing infinite bin locking. In this case the cookie can be used to iterate a
313 The following algorithm iterates a list and reverses the updates in the
314 case a concurrent update was done to the list while iterating. The idea is
315 that whenever we reacquire the lock, we check for updates to the cookie to
316 decide if we are still iterating the right list.
319 /* grab list and cookie */
320 cookie = object->list_cookie;
323 GstObject *item = GST_OBJECT (list->data);
324 /* need to ref the item before releasing the lock */
325 gst_object_ref (item);
328 ... use/change item here...
330 /* release item here */
331 gst_object_unref (item);
334 if (cookie != object->list_cookie) {
335 /* handle rollback caused by concurrent modification
336 * of the list here */
338 ...rollback changes to items...
340 /* grab new cookie and list */
341 cookie = object->list_cookie;
345 list = g_list_next (list);
352 GstIterator provides an easier way of retrieving elements in a concurrent
353 list. The following code example is equivalent to the previous example.
357 it = _get_iterator(object);
359 switch (gst_iterator_next (it, &item)) {
360 case GST_ITERATOR_OK:
362 ... use/change item here...
364 /* release item here */
365 gst_object_unref (item);
367 case GST_ITERATOR_RESYNC:
368 /* handle rollback caused by concurrent modification
369 * of the list here */
371 ...rollback changes to items...
373 /* resync iterator to start again */
374 gst_iterator_resync (it);
376 case GST_ITERATOR_DONE:
381 gst_iterator_free (it);