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