Commit 59fb10d0 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Add atomic swap and compare-and-swap

parent 1af9f7d3
......@@ -47,4 +47,7 @@ static inline uintptr_t vlc_atomic_dec (vlc_atomic_t *atom)
return vlc_atomic_sub (atom, 1);
}
VLC_EXPORT(uintptr_t, vlc_atomic_swap, (vlc_atomic_t *, uintptr_t));
VLC_EXPORT(uintptr_t, vlc_atomic_compare_swap, (vlc_atomic_t *, uintptr_t, uintptr_t));
#endif
......@@ -503,6 +503,8 @@ VLC_Compiler
vlc_atomic_get
vlc_atomic_set
vlc_atomic_add
vlc_atomic_swap
vlc_atomic_compare_swap
vlc_cond_broadcast
vlc_cond_destroy
vlc_cond_init
......
......@@ -46,6 +46,24 @@ uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v)
return __sync_add_and_fetch (&atom->u, v);
}
uintptr_t vlc_atomic_swap (vlc_atomic_t *atom, uintptr_t v)
{
/* grmbl, gcc does not provide an intrinsic for this! */
uintptr_t u;
do
u = vlc_atomic_get (atom);
while (vlc_atomic_compare_swap (atom, u, v) != u);
return u;
}
uintptr_t vlc_atomic_compare_swap (vlc_atomic_t *atom,
uintptr_t oldval, uintptr_t newval)
{
return __sync_val_compare_and_swap (&atom->u, oldval, newval);
}
#else
/* Worst-case fallback implementation with a mutex */
......@@ -78,4 +96,30 @@ uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v)
return v;
}
uintptr_t vlc_atomic_swap (vlc_atomic_t *atom, uintptr_t v)
{
uintptr_t u;
vlc_mutex_lock (&lock);
u = atom->u;
atom->u = v;
vlc_mutex_unlock (&lock);
return u;
}
uintptr_t vlc_atomic_compare_and_swap (vlc_atomic_t *atom,
uintptr_t oldval, uintptr_t newval)
{
uintptr_t u;
vlc_mutex_lock (&lock);
u = atom->u;
if (u == oldval)
atom->u = newval;
vlc_mutex_unlock (&lock);
return u;
}
#endif
......@@ -50,3 +50,22 @@ uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v)
return InterlockedExchangeAdd (&atom->s, v) + v;
#endif
}
uintptr_t vlc_atomic_swap (vlc_atomic_t *atom, uintptr_t v)
{
#if defined (WIN64)
return InterlockedExchange64 (&atom->s, v);
#else
return InterlockedExchange (&atom->s, v);
#endif
}
uintptr_t vlc_atomic_compare_swap (vlc_atomic_t *atom,
uintptr_t oldval, uintptr_t newval)
{
#if defined (WIN64)
return InterlockedCompareExchange64 (&atom->s, newval, oldval);
#else
return InterlockedCompareExchange (&atom->s, newval, oldval);
#endif
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment