GNOME Bugzilla – Bug 627293
GOnce support
Last modified: 2014-06-27 19:45:08 UTC
It would be nice to see support in Vala for executing blocks of code once, likely using GOnce. This could be done either with a keyword somewhat similar to lock (though likely not requiring a variable to operate on), or a way to specify methods which are only executed once. I don't see a good way to bind GOnce without support for static variables.
Yes - this would be nice. See also bug 672094.
Created attachment 241633 [details] [review] 0001-Add-bindings-to-GLib.Once.patch Fortunately Vala initializes everything to 0 which is just fine for GLib.Once: class MyClass { private GLib.Once<bool> internal1; private size_t internal2; public void run1 () { internal1.once(() => { stdout.printf("MyClass.run1(%p)\n", this); return false; }); } public void run2 () { if (GLib.Once.init_enter ((void **)(&internal2))) { stdout.printf("MyClass.run2(%p)\n", this); GLib.Once.init_leave((void **)(&internal2), (void *)1); } } } internal GLib.Once<MyClass> once_init1; internal uint runs1 = 0; void run1 () { unowned MyClass c = once_init1.once(() => { stdout.printf("%u\n", ++runs1); return new MyClass(); }); stdout.printf("%p\n", c); c.run1 (); } internal MyClass once_init2; internal uint runs2 = 0; void run2 () { if (GLib.Once.init_enter (&once_init2)) { stdout.printf("%u\n", ++runs2); GLib.Once.init_leave(&once_init2, new MyClass()); } stdout.printf("%p\n", once_init2); once_init2.run2 (); } int main() { run1 (); run1 (); stdout.printf("--------------\n"); run2 (); run2 (); return 0; } Output: 1 0x1e8cc00 MyClass.run1(0x1e8cc00) 0x1e8cc00 -------------- 1 0x1e8cc40 MyClass.run2(0x1e8cc40) 0x1e8cc40
Created attachment 241636 [details] [review] 0001-Add-bindings-to-GLib.Once.patch Update after discussion with Luca about types.
Created attachment 241730 [details] [review] 0001-Add-bindings-to-GLib.Once.patch Update - the once is not guaranteed to call its argument so it is safer to create separate delegate.
I still haven't understood what g_once passes to the func, because there's no parse_debug_flags. Also, what's wrong with ThreadFunc? The scope=async is even good to have here, so that any user data will be freed after the func is called.
(In reply to comment #5) > I still haven't understood what g_once passes to the func, because there's no > parse_debug_flags. Parse_debug_flags from example https://developer.gnome.org/glib/2.36/glib-Threads.html#g-once is just a name of function will be called. Otherwise I have no idea what you're referring to. > Also, what's wrong with ThreadFunc? The scope=async is even good to have here, > so that any user data will be freed after the func is called. GOnce<int> once; void do_it_once () { int value = 0; // value allocated on heap as it is referenced in closure once.once (() => { stdout.printf("Print it %d time\n", ++value); }); } int main () { do_it_once (); // Callback frees the value - OK do_it_once (); // Callback is never called }
(In reply to comment #6) > Parse_debug_flags from example > https://developer.gnome.org/glib/2.36/glib-Threads.html#g-once is just a name > of function will be called. Otherwise I have no idea what you're referring to. Yes, and it would have been useful to show at least the signature of the func. So what's the signature of func? > GOnce<int> once; > > void do_it_once () { > int value = 0; // value allocated on heap as it is referenced in closure > once.once (() => { > stdout.printf("Print it %d time\n", ++value); > }); > } > > int main () { > do_it_once (); // Callback frees the value - OK > do_it_once (); // Callback is never called > } Ok makes sense.
(In reply to comment #7) > (In reply to comment #6) > > Parse_debug_flags from example > > https://developer.gnome.org/glib/2.36/glib-Threads.html#g-once is just a name > > of function will be called. Otherwise I have no idea what you're referring to. > > Yes, and it would have been useful to show at least the signature of the func. > So what's the signature of func? > Well it is a macro (https://git.gnome.org/browse/glib/tree/glib/gthread.h?id=2.36.1#n238) but underlaying implementation uses GThreadFunc (https://git.gnome.org/browse/glib/tree/glib/gthread.h?id=2.36.1#n228). The difference is that once might not call the callback.
Patch looks fine to me. I'd like Evan to review it too before landing.
It would be nice to have a [CCode (default_value = "G_ONCE_INIT")] on the struct so that it gets initialized with G_ONCE_INIT instead of {0}. Also, you're missing spaces before the open parenthesis in a few places.
Created attachment 241771 [details] [review] 0001-Add-bindings-to-GLib.Once.patch Include CCode default_value and missing spaces.
commit f5a54052d1f7fb263bb8363934fabdc845f3a934 Author: Maciej Piechotka <uzytkownik2@gmail.com> Date: Tue Apr 16 13:53:13 2013 +0200 Add bindings to GLib.Once