1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module glib.MainLoop; 26 27 private import glib.ConstructionException; 28 private import glib.MainContext; 29 private import glib.Source; 30 private import glib.c.functions; 31 public import glib.c.types; 32 public import gtkc.glibtypes; 33 private import gtkd.Loader; 34 35 36 /** 37 * The `GMainLoop` struct is an opaque data type 38 * representing the main event loop of a GLib or GTK+ application. 39 */ 40 public class MainLoop 41 { 42 /** the main Gtk struct */ 43 protected GMainLoop* gMainLoop; 44 protected bool ownedRef; 45 46 /** Get the main Gtk struct */ 47 public GMainLoop* getMainLoopStruct(bool transferOwnership = false) 48 { 49 if (transferOwnership) 50 ownedRef = false; 51 return gMainLoop; 52 } 53 54 /** the main Gtk struct as a void* */ 55 protected void* getStruct() 56 { 57 return cast(void*)gMainLoop; 58 } 59 60 /** 61 * Sets our main struct and passes it to the parent class. 62 */ 63 public this (GMainLoop* gMainLoop, bool ownedRef = false) 64 { 65 this.gMainLoop = gMainLoop; 66 this.ownedRef = ownedRef; 67 } 68 69 ~this () 70 { 71 if ( Linker.isLoaded(LIBRARY_GLIB) && ownedRef ) 72 g_main_loop_unref(gMainLoop); 73 } 74 75 76 /** 77 * Creates a new #GMainLoop structure. 78 * 79 * Params: 80 * context = a #GMainContext (if %NULL, the default context will be used). 81 * isRunning = set to %TRUE to indicate that the loop is running. This 82 * is not very important since calling g_main_loop_run() will set this to 83 * %TRUE anyway. 84 * 85 * Returns: a new #GMainLoop. 86 * 87 * Throws: ConstructionException GTK+ fails to create the object. 88 */ 89 public this(MainContext context, bool isRunning) 90 { 91 auto __p = g_main_loop_new((context is null) ? null : context.getMainContextStruct(), isRunning); 92 93 if(__p is null) 94 { 95 throw new ConstructionException("null returned by new"); 96 } 97 98 this(cast(GMainLoop*) __p); 99 } 100 101 /** 102 * Returns the #GMainContext of @loop. 103 * 104 * Returns: the #GMainContext of @loop 105 */ 106 public MainContext getContext() 107 { 108 auto __p = g_main_loop_get_context(gMainLoop); 109 110 if(__p is null) 111 { 112 return null; 113 } 114 115 return new MainContext(cast(GMainContext*) __p); 116 } 117 118 /** 119 * Checks to see if the main loop is currently being run via g_main_loop_run(). 120 * 121 * Returns: %TRUE if the mainloop is currently being run. 122 */ 123 public bool isRunning() 124 { 125 return g_main_loop_is_running(gMainLoop) != 0; 126 } 127 128 /** 129 * Stops a #GMainLoop from running. Any calls to g_main_loop_run() 130 * for the loop will return. 131 * 132 * Note that sources that have already been dispatched when 133 * g_main_loop_quit() is called will still be executed. 134 */ 135 public void quit() 136 { 137 g_main_loop_quit(gMainLoop); 138 } 139 140 alias doref = ref_; 141 /** 142 * Increases the reference count on a #GMainLoop object by one. 143 * 144 * Returns: @loop 145 */ 146 public MainLoop ref_() 147 { 148 auto __p = g_main_loop_ref(gMainLoop); 149 150 if(__p is null) 151 { 152 return null; 153 } 154 155 return new MainLoop(cast(GMainLoop*) __p, true); 156 } 157 158 /** 159 * Runs a main loop until g_main_loop_quit() is called on the loop. 160 * If this is called for the thread of the loop's #GMainContext, 161 * it will process events from the loop, otherwise it will 162 * simply wait. 163 */ 164 public void run() 165 { 166 g_main_loop_run(gMainLoop); 167 } 168 169 /** 170 * Decreases the reference count on a #GMainLoop object by one. If 171 * the result is zero, free the loop and free all associated memory. 172 */ 173 public void unref() 174 { 175 g_main_loop_unref(gMainLoop); 176 } 177 178 /** 179 * Returns the currently firing source for this thread. 180 * 181 * Returns: The currently firing source or %NULL. 182 * 183 * Since: 2.12 184 */ 185 public static Source mainCurrentSource() 186 { 187 auto __p = g_main_current_source(); 188 189 if(__p is null) 190 { 191 return null; 192 } 193 194 return new Source(cast(GSource*) __p); 195 } 196 197 /** 198 * Returns the depth of the stack of calls to 199 * g_main_context_dispatch() on any #GMainContext in the current thread. 200 * That is, when called from the toplevel, it gives 0. When 201 * called from within a callback from g_main_context_iteration() 202 * (or g_main_loop_run(), etc.) it returns 1. When called from within 203 * a callback to a recursive call to g_main_context_iteration(), 204 * it returns 2. And so forth. 205 * 206 * This function is useful in a situation like the following: 207 * Imagine an extremely simple "garbage collected" system. 208 * 209 * |[<!-- language="C" --> 210 * static GList *free_list; 211 * 212 * gpointer 213 * allocate_memory (gsize size) 214 * { 215 * gpointer result = g_malloc (size); 216 * free_list = g_list_prepend (free_list, result); 217 * return result; 218 * } 219 * 220 * void 221 * free_allocated_memory (void) 222 * { 223 * GList *l; 224 * for (l = free_list; l; l = l->next); 225 * g_free (l->data); 226 * g_list_free (free_list); 227 * free_list = NULL; 228 * } 229 * 230 * [...] 231 * 232 * while (TRUE); 233 * { 234 * g_main_context_iteration (NULL, TRUE); 235 * free_allocated_memory(); 236 * } 237 * ]| 238 * 239 * This works from an application, however, if you want to do the same 240 * thing from a library, it gets more difficult, since you no longer 241 * control the main loop. You might think you can simply use an idle 242 * function to make the call to free_allocated_memory(), but that 243 * doesn't work, since the idle function could be called from a 244 * recursive callback. This can be fixed by using g_main_depth() 245 * 246 * |[<!-- language="C" --> 247 * gpointer 248 * allocate_memory (gsize size) 249 * { 250 * FreeListBlock *block = g_new (FreeListBlock, 1); 251 * block->mem = g_malloc (size); 252 * block->depth = g_main_depth (); 253 * free_list = g_list_prepend (free_list, block); 254 * return block->mem; 255 * } 256 * 257 * void 258 * free_allocated_memory (void) 259 * { 260 * GList *l; 261 * 262 * int depth = g_main_depth (); 263 * for (l = free_list; l; ); 264 * { 265 * GList *next = l->next; 266 * FreeListBlock *block = l->data; 267 * if (block->depth > depth) 268 * { 269 * g_free (block->mem); 270 * g_free (block); 271 * free_list = g_list_delete_link (free_list, l); 272 * } 273 * 274 * l = next; 275 * } 276 * } 277 * ]| 278 * 279 * There is a temptation to use g_main_depth() to solve 280 * problems with reentrancy. For instance, while waiting for data 281 * to be received from the network in response to a menu item, 282 * the menu item might be selected again. It might seem that 283 * one could make the menu item's callback return immediately 284 * and do nothing if g_main_depth() returns a value greater than 1. 285 * However, this should be avoided since the user then sees selecting 286 * the menu item do nothing. Furthermore, you'll find yourself adding 287 * these checks all over your code, since there are doubtless many, 288 * many things that the user could do. Instead, you can use the 289 * following techniques: 290 * 291 * 1. Use gtk_widget_set_sensitive() or modal dialogs to prevent 292 * the user from interacting with elements while the main 293 * loop is recursing. 294 * 295 * 2. Avoid main loop recursion in situations where you can't handle 296 * arbitrary callbacks. Instead, structure your code so that you 297 * simply return to the main loop and then get called again when 298 * there is more work to do. 299 * 300 * Returns: The main loop recursion level in the current thread 301 */ 302 public static int mainDepth() 303 { 304 return g_main_depth(); 305 } 306 307 /** 308 * Polls @fds, as with the poll() system call, but portably. (On 309 * systems that don't have poll(), it is emulated using select().) 310 * This is used internally by #GMainContext, but it can be called 311 * directly if you need to block until a file descriptor is ready, but 312 * don't want to run the full main loop. 313 * 314 * Each element of @fds is a #GPollFD describing a single file 315 * descriptor to poll. The @fd field indicates the file descriptor, 316 * and the @events field indicates the events to poll for. On return, 317 * the @revents fields will be filled with the events that actually 318 * occurred. 319 * 320 * On POSIX systems, the file descriptors in @fds can be any sort of 321 * file descriptor, but the situation is much more complicated on 322 * Windows. If you need to use g_poll() in code that has to run on 323 * Windows, the easiest solution is to construct all of your 324 * #GPollFDs with g_io_channel_win32_make_pollfd(). 325 * 326 * Params: 327 * fds = file descriptors to poll 328 * nfds = the number of file descriptors in @fds 329 * timeout = amount of time to wait, in milliseconds, or -1 to wait forever 330 * 331 * Returns: the number of entries in @fds whose @revents fields 332 * were filled in, or 0 if the operation timed out, or -1 on error or 333 * if the call was interrupted. 334 * 335 * Since: 2.20 336 */ 337 public static int poll(GPollFD* fds, uint nfds, int timeout) 338 { 339 return g_poll(fds, nfds, timeout); 340 } 341 }