GNOME Bugzilla – Bug 69668
Add GLib analogy to pthread_once
Last modified: 2011-02-18 16:07:08 UTC
Having GOnce datatype and a g_once (GOnce* once, GVoidFunc initalize) function, we could make a general solution to the problems of #61228 and the static mutex on plaform without native static mutexes: See http://bugzilla.gnome.org/show_bug.cgi?id=61228 http://mail.gnome.org/archives/gtk-devel-list/2001-May/msg00147.html We can use code like (beware: pseudocode) g_once (GOnce* once, GVoidFunc initalize) { if (*once) return; G_LOCK(once); initalize(); G_UNLOCK(once); *once = TRUE; } The values of READ_MEMORY_BARRIER of glibc/linuxthreads/sysdeps/*/pt-machine.h will be of interest, as the source of pthread_once in glibc looks like: /* Test without locking first for speed */ if (*once_control == DONE) { READ_MEMORY_BARRIER(); return 0; } /* Lock and test again */ READ_MEMORY_BARRIER is empty for arm, cris, hppa, i386, i386/i686, ia64, m68k, sh, s390/s390-32, s390/s390-64 and set to some asm for sparc/sparc32, sparc/sparc64, alpha, mips, powerpc. For the first group I think, it would be save to use the double locking idiom. The second group would need full locking unless we implement the read memory barrier ourself copying from linuxthreads, which I wouldn't like. NB for implementing: Beware of recursion into the GOnce handler! (A whole other possibility would be to simply __use__, what pthread_once offers and use the full locking on platforms, which have no counterpart. Thinking twice about it, this seems to be the best solution.)
Created attachment 6767 [details] [review] a full implementation in terms of g_thread abstraction
Attachment 6767 [details] The implementation uses a double check technique to provide a very fast go over in almost all cases where the intializer has been already run. It bases on the atomic read access for machine words. When in doubt the full locking is performed and initializer is run if needed.
Your solution is not guaranteed to work. We have this discussion every half year. Basically the double check pattern is not safe for some (admittedly not so common) systems. We could use this technique, where it is allowed, and fall back to full locking on the other platforms. I think, we should support calling a function, which takes an argument (gpointer) and returns a gpointer to make this more useful. Such an implementation could be used to implement g_static_mutex_get_mutex_impl, which is my aim in including g_once. Your implementation couldn't do that. Actually the pthread implementation is of very limited use due to that. The proposed interface would look like this: gpointer g_once (GOnce* once, GThreadFunc initalize, gpointer arg);
*** Bug 55102 has been marked as a duplicate of this bug. ***
Attached you'll find an implementation of GOnce and gpointer g_once (GOnce* once, GThreadFunc initalize, gpointer arg) and a test in thread-test.c (modelled after the one in the patch of Miroslaw) Also it uses the information, whether double checked locking is safe to use, to make GStaticMutex faster. Docs are not included yet, but should be no problem getting in, if and when this is committed.
Created attachment 6807 [details] [review] patch to implement GOnce and g_once
This looks good to commit to me; I'm a little concerned about the fallback implementation being a bottleneck on sparc though. (ppc also a possible concern, but I don't think people care as much about GNOME performance on slow ppc machines as on slow sparc machines) Brian - do you know someone knowledgable about the low-level sparc details you could get to take look at this?
I'll not have internet access for the next 2 month. So if you want that in, you got to do it yourself. Thanks. This is indeed the last time I'll check my email for that long. Scary.
Scary indeed. I've committed your patch with docs.