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 /** 141 * Increases the reference count on a #GMainLoop object by one. 142 * 143 * Returns: @loop 144 */ 145 public MainLoop doref() 146 { 147 auto p = g_main_loop_ref(gMainLoop); 148 149 if(p is null) 150 { 151 return null; 152 } 153 154 return new MainLoop(cast(GMainLoop*) p, true); 155 } 156 157 /** 158 * Runs a main loop until g_main_loop_quit() is called on the loop. 159 * If this is called for the thread of the loop's #GMainContext, 160 * it will process events from the loop, otherwise it will 161 * simply wait. 162 */ 163 public void run() 164 { 165 g_main_loop_run(gMainLoop); 166 } 167 168 /** 169 * Decreases the reference count on a #GMainLoop object by one. If 170 * the result is zero, free the loop and free all associated memory. 171 */ 172 public void unref() 173 { 174 g_main_loop_unref(gMainLoop); 175 } 176 177 /** 178 * Returns the currently firing source for this thread. 179 * 180 * Returns: The currently firing source or %NULL. 181 * 182 * Since: 2.12 183 */ 184 public static Source mainCurrentSource() 185 { 186 auto p = g_main_current_source(); 187 188 if(p is null) 189 { 190 return null; 191 } 192 193 return new Source(cast(GSource*) p); 194 } 195 196 /** 197 * Returns the depth of the stack of calls to 198 * g_main_context_dispatch() on any #GMainContext in the current thread. 199 * That is, when called from the toplevel, it gives 0. When 200 * called from within a callback from g_main_context_iteration() 201 * (or g_main_loop_run(), etc.) it returns 1. When called from within 202 * a callback to a recursive call to g_main_context_iteration(), 203 * it returns 2. And so forth. 204 * 205 * This function is useful in a situation like the following: 206 * Imagine an extremely simple "garbage collected" system. 207 * 208 * |[<!-- language="C" --> 209 * static GList *free_list; 210 * 211 * gpointer 212 * allocate_memory (gsize size) 213 * { 214 * gpointer result = g_malloc (size); 215 * free_list = g_list_prepend (free_list, result); 216 * return result; 217 * } 218 * 219 * void 220 * free_allocated_memory (void) 221 * { 222 * GList *l; 223 * for (l = free_list; l; l = l->next); 224 * g_free (l->data); 225 * g_list_free (free_list); 226 * free_list = NULL; 227 * } 228 * 229 * [...] 230 * 231 * while (TRUE); 232 * { 233 * g_main_context_iteration (NULL, TRUE); 234 * free_allocated_memory(); 235 * } 236 * ]| 237 * 238 * This works from an application, however, if you want to do the same 239 * thing from a library, it gets more difficult, since you no longer 240 * control the main loop. You might think you can simply use an idle 241 * function to make the call to free_allocated_memory(), but that 242 * doesn't work, since the idle function could be called from a 243 * recursive callback. This can be fixed by using g_main_depth() 244 * 245 * |[<!-- language="C" --> 246 * gpointer 247 * allocate_memory (gsize size) 248 * { 249 * FreeListBlock *block = g_new (FreeListBlock, 1); 250 * block->mem = g_malloc (size); 251 * block->depth = g_main_depth (); 252 * free_list = g_list_prepend (free_list, block); 253 * return block->mem; 254 * } 255 * 256 * void 257 * free_allocated_memory (void) 258 * { 259 * GList *l; 260 * 261 * int depth = g_main_depth (); 262 * for (l = free_list; l; ); 263 * { 264 * GList *next = l->next; 265 * FreeListBlock *block = l->data; 266 * if (block->depth > depth) 267 * { 268 * g_free (block->mem); 269 * g_free (block); 270 * free_list = g_list_delete_link (free_list, l); 271 * } 272 * 273 * l = next; 274 * } 275 * } 276 * ]| 277 * 278 * There is a temptation to use g_main_depth() to solve 279 * problems with reentrancy. For instance, while waiting for data 280 * to be received from the network in response to a menu item, 281 * the menu item might be selected again. It might seem that 282 * one could make the menu item's callback return immediately 283 * and do nothing if g_main_depth() returns a value greater than 1. 284 * However, this should be avoided since the user then sees selecting 285 * the menu item do nothing. Furthermore, you'll find yourself adding 286 * these checks all over your code, since there are doubtless many, 287 * many things that the user could do. Instead, you can use the 288 * following techniques: 289 * 290 * 1. Use gtk_widget_set_sensitive() or modal dialogs to prevent 291 * the user from interacting with elements while the main 292 * loop is recursing. 293 * 294 * 2. Avoid main loop recursion in situations where you can't handle 295 * arbitrary callbacks. Instead, structure your code so that you 296 * simply return to the main loop and then get called again when 297 * there is more work to do. 298 * 299 * Returns: The main loop recursion level in the current thread 300 */ 301 public static int mainDepth() 302 { 303 return g_main_depth(); 304 } 305 306 /** 307 * Polls @fds, as with the poll() system call, but portably. (On 308 * systems that don't have poll(), it is emulated using select().) 309 * This is used internally by #GMainContext, but it can be called 310 * directly if you need to block until a file descriptor is ready, but 311 * don't want to run the full main loop. 312 * 313 * Each element of @fds is a #GPollFD describing a single file 314 * descriptor to poll. The @fd field indicates the file descriptor, 315 * and the @events field indicates the events to poll for. On return, 316 * the @revents fields will be filled with the events that actually 317 * occurred. 318 * 319 * On POSIX systems, the file descriptors in @fds can be any sort of 320 * file descriptor, but the situation is much more complicated on 321 * Windows. If you need to use g_poll() in code that has to run on 322 * Windows, the easiest solution is to construct all of your 323 * #GPollFDs with g_io_channel_win32_make_pollfd(). 324 * 325 * Params: 326 * fds = file descriptors to poll 327 * nfds = the number of file descriptors in @fds 328 * timeout = amount of time to wait, in milliseconds, or -1 to wait forever 329 * 330 * Returns: the number of entries in @fds whose @revents fields 331 * were filled in, or 0 if the operation timed out, or -1 on error or 332 * if the call was interrupted. 333 * 334 * Since: 2.20 335 */ 336 public static int poll(GPollFD* fds, uint nfds, int timeout) 337 { 338 return g_poll(fds, nfds, timeout); 339 } 340 }