Search code examples
glib

Is g_ptr_array_add () in GLib thread safe?


The documentation says:

          void  g_ptr_array_insert (GPtrArray *array,
                gint index_,
                gpointer data);

Inserts an element into the pointer array at the given index. The array will grow in size automatically if necessary.

Same question for g_ptr_array_add().
Documentation is silent about thread safety of these functions. The following functions are described expressly to be thread-safe:

      g_ptr_array_free ()
      g_ptr_array_ref()
      g_ptr_array_unref ()

What if multiple-threads execute g_ptr_array_insert() at the same time on the same array of pointers? Do I have to provide thread safety myself?


Solution

  • No, it's not thread-safe (just as almost all GLib data types; source, see “you must coordinate accesses…”). Chances are that two threads enter marked line simultaneously.

    static void
    g_ptr_array_maybe_expand (GRealPtrArray *array,
                              gint           len)
    {
      if ((array->len + len) > array->alloc)
        {
          guint old_alloc = array->alloc;
          array->alloc = g_nearest_pow (array->len + len);
          array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
          array->pdata = g_realloc (array->pdata, sizeof (gpointer) * array->alloc); // here
          if (G_UNLIKELY (g_mem_gc_friendly))
            for ( ; old_alloc < array->alloc; old_alloc++)
              array->pdata [old_alloc] = NULL;
        }
    }
    
    void
    g_ptr_array_add (GPtrArray *array,
                     gpointer   data)
    {
      GRealPtrArray *rarray = (GRealPtrArray *)array;
    
      g_return_if_fail (rarray);
    
      g_ptr_array_maybe_expand (rarray, 1);
    
      rarray->pdata[rarray->len++] = data;
    }
    

    Provide your own locking using, for example, GMutex.