Atomic Ints (Was: GObject thread safety)
- From: Sebastian Wilhelmi <wilhelmi ira uka de>
- To: Alex Larsson <alexl redhat com>
- Cc: Tim Janik <timj gtk org>, Michael Meeks <michael ximian com>, Gtk+ Developers <gtk-devel-list gnome org>, Owen Taylor <otaylor redhat com>
- Subject: Atomic Ints (Was: GObject thread safety)
- Date: Fri, 02 Nov 2001 14:38:21 +0100
Hi,
> Otoh, we could add some atomic ops to implement refcounting that is MT
> safe without having the overhead of locking. I've did this for the
> ref/unref in the Mozilla javascript engine, and it makes quite a
> difference (compared to locks).
I've for some time now wanted to include that and given, how long the GLib API
of 2.0 will be fixed this indeed looks like a valuable addition.
Until now I hesitated, because:
1) Its will add much asm-code-snippets to glib. That might prove hard to
maintain.
2) I do not know of any _L_GPL implementation of this yet. We have nspr
under GPL, so we would have to ask to include the asm-snippets
verbatim, even though I'm sure, they would allow using that.
3) I had other things to do, that my prof deemed more important ;-)
We could add special asm code for different platforms later and for the time
being just present a sane API and make a fallback implementation and maybe a
linux/x86 as the obviously most important one.
So I want to hereby suggest adding:
/* not opaque, but prolly in glibconfig.h */
typedef struct _GAtomicInt GAtomicInt;
/* initialize it, either compile time or run time, just like GStatic* */
#define G_ATOMIC_INT_INIT(init_value) ...
void g_atomic_int_init (GAtomicInt *atomic_int, gint init_value);
/* increment by one; return new value */
gint g_atomic_int_inc (GAtomicInt *atomic_int);
/* decrement by one; return new value */
gint g_atomic_int_dec (GAtomicInt *atomic_int);
/* Reads the old value and set the new value atomically */
gint g_atomic_int_replace (GAtomicInt *atomic_int);
/* Just relying on a write or read to an int being atomic, just to for
information encapsulating for this special case. Prolly just macros */
void g_atomic_int_set (GAtomicInt *atomic_int, gint value);
gint g_atomic_int_get (GAtomicInt *atomic_int);
/* This last one doesn't seem very necessary, but is included in
libnspr. */
gint g_atomic_int_add (GAtomicInt *atomic_int, gint to_add);
/* Free allocated resources, if any */
void g_atomic_int_free (GAtomicInt *atomic_int);
Why not doing it like nspr, i.e.
gint g_atomic_int_inc (gint *atomic_int);
1) The nspr fallback uses some (10 IIRC) mutexes for all atomic ints
(chosen by a hash value of the address), thus you can get some
contention (Ok. IRL this shouldn't be a problem). So the above solution
is more clean.
2) You do not by accident use the value directly. Even though of course
the get and set operation is atomic by nature (I would claim), it is
good to set and get those vars via a function to make it clear, that
the values are volatile by nature.
Open question:
GAtomicInt of course is just a struct with GStaticMutex and a gint for the
fallback case. For the optimized case we of course want it to only be a gint.
But as we probably only support the asm-Syntax of gcc, we get a problem: The
size of GAtomicInt depends on the compiler used for compiling glib. That
means, that a glib compiled by gcc is not binary compatible with a glib
compiled by some other compiler for the same platform and programs assuming so
will fail in mysterious ways. So _that_ might be a real reason to do it like
nspr actually.
(BTW.: It might seem, that glib already is binary incompatibel
between different compilers on the same platform, but I don't think, it
really is, though I might be wrong)
So in retrospect I changed my mind ;-) We do i like that: (a mixture between
nspr (implementation) and the first idea (interface))
typedef volatile gint GAtomicInt;
/* increment by one; return new value */
gint g_atomic_int_inc (GAtomicInt *atomic_int);
/* decrement by one; return new value */
gint g_atomic_int_dec (GAtomicInt *atomic_int);
/* Reads the old value and set the new value atomically */
gint g_atomic_int_replace (GAtomicInt *atomic_int);
/* This last one doesn't seem very necessary, but is included in
libnspr. */
gint g_atomic_int_add (GAtomicInt *atomic_int, gint to_add);
What do you think? Please choose the version and I will cook up a patch with
just the fallback implementation so far (thus fixing the API).
Ciao,
Sebastian
--
Sebastian Wilhelmi
mailto:wilhelmi ira uka de
http://goethe.ira.uka.de/~wilhelmi
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]