GLib.main_depth
Description: Reference for GLib.main_depth

### Function

# GLibmain_depth

#### Declaration [src]

    gint
    g_main_depth (
      void
    )

#### Description [src]

Returns the depth of the stack of calls to `g_main_context_dispatch()` on any `GMainContext` in the current thread.

That is, when called from the top level, it gives `0`. When called from within a callback from `g_main_context_iteration()` (or `g_main_loop_run()`, etc.) it returns `1`. When called from within a callback to a recursive call to `g_main_context_iteration()`, it returns `2`. And so forth.

This function is useful in a situation like the following: Imagine an extremely simple ‘garbage collected’ system.

    static GList *free_list;

    gpointer
    allocate_memory (gsize size)
    {
      gpointer result = g_malloc (size);
      free_list = g_list_prepend (free_list, result);
      return result;
    }

    void
    free_allocated_memory (void)
    {
      GList *l;
      for (l = free_list; l; l = l->next);
        g_free (l->data);
      g_list_free (free_list);
      free_list = NULL;
     }

    [...]

    while (TRUE);
     {
       g_main_context_iteration (NULL, TRUE);
       free_allocated_memory();
      }

This works from an application, however, if you want to do the same thing from a library, it gets more difficult, since you no longer control the main loop. You might think you can simply use an idle function to make the call to `free_allocated_memory()`, but that doesn’t work, since the idle function could be called from a recursive callback. This can be fixed by using `g_main_depth()`

    gpointer
    allocate_memory (gsize size)
    {
      FreeListBlock *block = g_new (FreeListBlock, 1);
      block->mem = g_malloc (size);
      block->depth = g_main_depth ();
      free_list = g_list_prepend (free_list, block);
      return block->mem;
    }

    void
    free_allocated_memory (void)
    {
      GList *l;

      int depth = g_main_depth ();
      for (l = free_list; l; );
        {
          GList *next = l->next;
          FreeListBlock *block = l->data;
          if (block->depth > depth)
            {
              g_free (block->mem);
              g_free (block);
              free_list = g_list_delete_link (free_list, l);
            }

          l = next;
        }
      }

There is a temptation to use `g_main_depth()` to solve problems with reentrancy. For instance, while waiting for data to be received from the network in response to a menu item, the menu item might be selected again. It might seem that one could make the menu item’s callback return immediately and do nothing if `g_main_depth()` returns a value greater than 1. However, this should be avoided since the user then sees selecting the menu item do nothing. Furthermore, you’ll find yourself adding these checks all over your code, since there are doubtless many, many things that the user could do. Instead, you can use the following techniques:

1. Use `gtk_widget_set_sensitive()` or modal dialogs to prevent the user from interacting with elements while the main loop is recursing.

2. Avoid main loop recursion in situations where you can’t handle arbitrary callbacks. Instead, structure your code so that you simply return to the main loop and then get called again when there is more work to do.

#### Return value

Type: `gint`

The main loop recursion level in the current thread.