/** * gst_mini_object_unlock: * @object: the mini-object to unlock * @flags: #GstLockFlags * * Unlock the mini-object with the specified access mode in @flags. */ void gst_mini_object_unlock (GstMiniObject * object, GstLockFlags flags) { gint access_mode, state, newstate; g_return_if_fail (object != NULL); g_return_if_fail (GST_MINI_OBJECT_IS_LOCKABLE (object)); do { access_mode = flags & FLAG_MASK; newstate = state = g_atomic_int_get (&object->lockstate); GST_CAT_TRACE (GST_CAT_LOCKING, "unlock %p: state %08x, access_mode %d", object, state, access_mode); if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) { /* shared counter */ g_return_if_fail (state >= SHARE_ONE); newstate -= SHARE_ONE; access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE; } if (access_mode) { g_return_if_fail ((state & access_mode) == access_mode); /* decrease the refcount */ newstate -= LOCK_ONE; /* last refcount, unset access_mode */ if ((newstate & LOCK_FLAG_MASK) == access_mode) newstate &= ~LOCK_FLAG_MASK; } } while (!g_atomic_int_compare_and_exchange (&object->lockstate, state, newstate)); }
/** * gst_mini_object_lock: * @object: the mini-object to lock * @flags: #GstLockFlags * * Lock the mini-object with the specified access mode in @flags. * * Returns: %TRUE if @object could be locked. */ gboolean gst_mini_object_lock (GstMiniObject * object, GstLockFlags flags) { gint access_mode, state, newstate; g_return_val_if_fail (object != NULL, FALSE); g_return_val_if_fail (GST_MINI_OBJECT_IS_LOCKABLE (object), FALSE); if (G_UNLIKELY (object->flags & GST_MINI_OBJECT_FLAG_LOCK_READONLY && flags & GST_LOCK_FLAG_WRITE)) return FALSE; do { access_mode = flags & FLAG_MASK; newstate = state = g_atomic_int_get (&object->lockstate); GST_CAT_TRACE (GST_CAT_LOCKING, "lock %p: state %08x, access_mode %d", object, state, access_mode); if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) { /* shared ref */ newstate += SHARE_ONE; access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE; } /* shared counter > 1 and write access is not allowed */ if (((state & GST_LOCK_FLAG_WRITE) != 0 || (access_mode & GST_LOCK_FLAG_WRITE) != 0) && IS_SHARED (newstate)) goto lock_failed; if (access_mode) { if ((state & LOCK_FLAG_MASK) == 0) { /* nothing mapped, set access_mode */ newstate |= access_mode; } else { /* access_mode must match */ if ((state & access_mode) != access_mode) goto lock_failed; } /* increase refcount */ newstate += LOCK_ONE; } } while (!g_atomic_int_compare_and_exchange (&object->lockstate, state, newstate)); return TRUE; lock_failed: { GST_CAT_DEBUG (GST_CAT_LOCKING, "lock failed %p: state %08x, access_mode %d", object, state, access_mode); return FALSE; } }
/** * gst_mini_object_is_writable: * @mini_object: the mini-object to check * * If @mini_object has the LOCKABLE flag set, check if the current EXCLUSIVE * lock on @object is the only one, this means that changes to the object will * not be visible to any other object. * * If the LOCKABLE flag is not set, check if the refcount of @mini_object is * exactly 1, meaning that no other reference exists to the object and that the * object is therefore writable. * * Modification of a mini-object should only be done after verifying that it * is writable. * * Returns: TRUE if the object is writable. */ gboolean gst_mini_object_is_writable (const GstMiniObject * mini_object) { gboolean result; g_return_val_if_fail (mini_object != NULL, FALSE); if (GST_MINI_OBJECT_IS_LOCKABLE (mini_object)) { result = !IS_SHARED (g_atomic_int_get (&mini_object->lockstate)); } else { result = (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1); } return result; }