Beispiel #1
0
/**
 * 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;
  }
}
Beispiel #3
0
/**
 * 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;
}