From 6bb654922815d2776bb04a36c481a2a82ca09c3f Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 10 Feb 2005 14:49:29 +0000 Subject: [PATCH] docs/design/part-MT-refcounting.txt (Refcounting): Some grammar/clarity fixes, and added a section on child structure... Original commit message from CVS: 2005-02-10 Andy Wingo * docs/design/part-MT-refcounting.txt (Refcounting): Some grammar/clarity fixes, and added a section on child structures of shared refcounted objects. --- ChangeLog | 6 +++ docs/design/part-MT-refcounting.txt | 83 ++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 00adcc5d47..be987a9951 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-02-10 Andy Wingo + + * docs/design/part-MT-refcounting.txt (Refcounting): Some + grammar/clarity fixes, and added a section on child structures of + shared refcounted objects. + 2005-02-10 Andy Wingo * docs/design/part-MT-refcounting.txt: Fill to 80 columns. diff --git a/docs/design/part-MT-refcounting.txt b/docs/design/part-MT-refcounting.txt index 36de3fd634..4f788d3eea 100644 --- a/docs/design/part-MT-refcounting.txt +++ b/docs/design/part-MT-refcounting.txt @@ -15,31 +15,34 @@ MT safety techniques Several design patterns are used to guarantee object consistency in GStreamer. This is an overview of the methods used in various GStreamer subsystems. -Refcounting +Refcounting: - All objects have a refcount associated with them. Each reference obtained to - the object should increase the refcount and each reference lost should - decrease the refcount. + All shared objects have a refcount associated with them. Each reference + obtained to the object should increase the refcount and each reference lost + should decrease the refcount. The refcounting is used to make sure that when another thread destroys the object, the ones which still hold a reference to the object do not read from invalid memory when accessing the object. - It is a requirement that when two threads have a handle to an object, the - refcount must be one, this means that when one thread passes an object to - another thread it must increase the refcount. This requirement makes sure that - one thread cannot suddenly dispose the object making the other thread crash - when it tries to access the pointer to invalid memory. + Refcounting is also used to ensure that mutable data structures are only + modified when they are owned by the calling code. -Copy-on-write: + It is a requirement that when two threads have a handle on an object, the + refcount must be more than one. This means that when one thread passes an + object to another thread it must increase the refcount. This requirement makes + sure that one thread cannot suddenly dispose the object making the other + thread crash when it tries to access the pointer to invalid memory. - All object have a refcount associated with them. Each reference obtained to +Shared data structures and writability: + + All objects have a refcount associated with them. Each reference obtained to the object should increase the refcount and each reference lost should decrease the refcount. Each thread having a refcount to the object can safely read from the object. but modifications made to the object should be preceeded with a - _copy_on_write() function call. This function will check the refcount of the + _get_writable() function call. This function will check the refcount of the object and if the object is referenced by more than one instance, a copy is made of the object that is then by definition only referenced from the calling thread. This new copy is then modifyable without being visible to other @@ -51,15 +54,46 @@ Copy-on-write: The advantage of this method is that no reader/writers locks are needed. all threads can concurrently read but writes happen locally on a new copy. In most - cases _copy_on_write() can avoid a real copy because the calling method is the + cases _get_writable() can avoid a real copy because the calling method is the only one holding a reference, wich makes read/writes very cheap. The drawback is that sometimes 1 needless copy can be done. This would happen - when N threads call _copy_on_write() at the same time, all seeing that N - references are held to the object. In this case 1 copy too many will be done. + when N threads call _get_writable() at the same time, all seeing that N + references are held on the object. In this case 1 copy too many will be done. This is not a problem in any practical situation because the copy operation is fast. +Mutable substructures: + + Special techniques are necessary to ensure the consistency of compound shared + objects. As mentioned above, shared objects need to have a reference count of + 1 if they are to be modified. Implicit in this assumption is that all parts of + the shared object belong only to the object. For example, a GstStructure in + one GstCaps object should not belong to any other GstCaps object. This + condition suggests a parent-child relationship: structures can only be added + to parent object if they do not already have a parent object. + + In addition, these substructures must not be modified while more than one code + segment has a reference on the parent object. For example, if the user creates + a GstStructure, adds it to a GstCaps, and the GstCaps is then referenced by + other code segments, the GstStructure should then become immutable, so that + changes to that data structure do not affect other parts of the code. This + means that the child is only mutable when the parent's reference count is 1, + as well as when the child structure has no parent. + + The general solution to this problem is to include a field in child structures + pointing to the parent's atomic reference count. When set to NULL, this + indicates that the child has no parent. Otherwise, procedures that modify the + child structure must check if the parent's refcount is 1, and otherwise must + cause an error to be signaled. + + Note that this is an internal implementation detail; application or plugin + code that calls _get_writable() on an object is guaranteed to receive an + object of refcount 1, which must then be writable. The only trick is that a + pointer to a child structure of an object is only valid while the calling code + has a reference on the parent object, because the parent is the owner of the + child. + Object locking: For objects that contain state information and generally have a longer @@ -127,22 +161,23 @@ Objects object if the FLOATING flag is set. The act of taking ownership of an object is then performed as a _ref() followed by a _sink() call on the object. - Sinking objects is very usefull because you don't have to worry about the - lifetime of these sunken objects anymore since it is managed by the owner - element. + The float/sink process is very useful when initializing elements that will + then be placed under control of a parent. The floating ref keeps the object + alive until it is parented, and once the object is parented you can forget + about it. * parent-child relations - One can create parent child relationships with the _object_set_parent() - method. This method sinks the object and assigns its parent property to that - of the managing parent. + One can create parent-child relationships with the _object_set_parent() + method. This method refs and sinks the object and assigns its parent property + to that of the managing parent. The child is said to have a weak link to the parent since the refcount of the parent is not increased in this process. This means that if the parent is disposed it has to unset itself as the parent of the object before disposing itself, else the child object holds a parent pointer to invalid memory. - The responsabilites for an object that sinks other objects are summarised as: + The responsibilites for an object that sinks other objects are summarised as: - taking ownership of the object - call _object_set_parent() to set itself as the object parent, this call @@ -223,11 +258,11 @@ Objects * Accessor methods For aplications it is encouraged to use the public methods of the object. Most - usefull operations can be performed with the methods so it is seldom required + useful operations can be performed with the methods so it is seldom required to access the public fields manually. All accessor methods that return an object should increase the refcount of the - returned object. The called should _unref() the object after usage. Each + returned object. The caller should _unref() the object after usage. Each method should state this refcounting policy in the documentation. * Accessing lists