View | Details | Raw Unified | Return to bug 398548
Collapse All | Expand All

(-)gtype.c (-47 / +76 lines)
Lines 59-67 Link Here
59
 * - _Wm:	[Write-locked invocation, mutatable]
59
 * - _Wm:	[Write-locked invocation, mutatable]
60
 *   like _W, but the write lock might be released and reacquired
60
 *   like _W, but the write lock might be released and reacquired
61
 *   during invocation, watch your pointers
61
 *   during invocation, watch your pointers
62
 * - _WmREC:    [Write-locked invocation, mutatable, recursive]
63
 *   like _Wm, but also acquires recursive mutex class_init_rec_mutex
62
 */
64
 */
63
65
64
static GStaticRWLock            type_rw_lock = G_STATIC_RW_LOCK_INIT;
65
#ifdef LOCK_DEBUG
66
#ifdef LOCK_DEBUG
66
#define G_READ_LOCK(rw_lock)    do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0)
67
#define G_READ_LOCK(rw_lock)    do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0)
67
#define G_READ_UNLOCK(rw_lock)  do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0)
68
#define G_READ_UNLOCK(rw_lock)  do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0)
Lines 141-147 Link Here
141
									 const GTypeInfo	*info,
142
									 const GTypeInfo	*info,
142
									 const GTypeValueTable	*value_table);
143
									 const GTypeValueTable	*value_table);
143
static inline void			type_data_ref_Wm		(TypeNode		*node);
144
static inline void			type_data_ref_Wm		(TypeNode		*node);
144
static inline void			type_data_unref_Wm		(TypeNode		*node,
145
static inline void			type_data_unref_WmREC		(TypeNode		*node,
145
									 gboolean		 uncached);
146
									 gboolean		 uncached);
146
static void				type_data_last_unref_Wm		(GType			 type,
147
static void				type_data_last_unref_Wm		(GType			 type,
147
									 gboolean		 uncached);
148
									 gboolean		 uncached);
Lines 297-302 Link Here
297
298
298
299
299
/* --- variables --- */
300
/* --- variables --- */
301
static GStaticRWLock   type_rw_lock = G_STATIC_RW_LOCK_INIT;
302
static GStaticRecMutex class_init_rec_mutex = G_STATIC_REC_MUTEX_INIT;
300
static guint           static_n_class_cache_funcs = 0;
303
static guint           static_n_class_cache_funcs = 0;
301
static ClassCacheFunc *static_class_cache_funcs = NULL;
304
static ClassCacheFunc *static_class_cache_funcs = NULL;
302
static guint           static_n_iface_check_funcs = 0;
305
static guint           static_n_iface_check_funcs = 0;
Lines 1086-1108 Link Here
1086
}
1089
}
1087
1090
1088
static inline void
1091
static inline void
1089
type_data_unref_Wm (TypeNode *node,
1092
type_data_unref_WmREC (TypeNode *node,
1090
		    gboolean  uncached)
1093
                       gboolean  uncached)
1091
{
1094
{
1092
  g_assert (node->data && node->data->common.ref_count);
1095
  g_assert (node->data && node->data->common.ref_count);
1093
  
1094
  if (node->data->common.ref_count > 1)
1096
  if (node->data->common.ref_count > 1)
1095
    node->data->common.ref_count -= 1;
1097
    node->data->common.ref_count -= 1;
1096
  else
1098
  else
1097
    {
1099
    {
1100
      GType node_type = NODE_TYPE (node);
1098
      if (!node->plugin)
1101
      if (!node->plugin)
1099
	{
1102
	{
1100
	  g_warning ("static type `%s' unreferenced too often",
1103
	  g_warning ("static type `%s' unreferenced too often",
1101
		     NODE_NAME (node));
1104
		     NODE_NAME (node));
1102
	  return;
1105
	  return;
1103
	}
1106
	}
1104
      
1107
      G_WRITE_UNLOCK (&type_rw_lock);
1105
      type_data_last_unref_Wm (NODE_TYPE (node), uncached);
1108
      g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
1109
      G_WRITE_LOCK (&type_rw_lock);
1110
      type_data_last_unref_Wm (node_type, uncached);
1111
      g_static_rec_mutex_unlock (&class_init_rec_mutex);
1106
    }
1112
    }
1107
}
1113
}
1108
1114
Lines 1437-1443 Link Here
1437
      g_type_plugin_unuse (iholder->plugin);
1443
      g_type_plugin_unuse (iholder->plugin);
1438
      G_WRITE_LOCK (&type_rw_lock);
1444
      G_WRITE_LOCK (&type_rw_lock);
1439
      
1445
      
1440
      type_data_unref_Wm (iface, FALSE);
1446
      type_data_unref_WmREC (iface, FALSE);
1441
    }
1447
    }
1442
}
1448
}
1443
1449
Lines 2057-2063 Link Here
2057
      g_type_plugin_unuse (node->plugin);
2063
      g_type_plugin_unuse (node->plugin);
2058
      G_WRITE_LOCK (&type_rw_lock);
2064
      G_WRITE_LOCK (&type_rw_lock);
2059
      if (ptype)
2065
      if (ptype)
2060
	type_data_unref_Wm (lookup_type_node_I (ptype), FALSE);
2066
	type_data_unref_WmREC (lookup_type_node_I (ptype), FALSE);
2061
    }
2067
    }
2062
}
2068
}
2063
2069
Lines 2173-2179 Link Here
2173
  if ((type_id & TYPE_ID_MASK) ||
2179
  if ((type_id & TYPE_ID_MASK) ||
2174
      type_id > G_TYPE_FUNDAMENTAL_MAX)
2180
      type_id > G_TYPE_FUNDAMENTAL_MAX)
2175
    {
2181
    {
2176
      g_warning ("attempt to register fundamental type `%s' with invalid type id (%lu)",
2182
      g_warning ("attempt to register fundamental type `%s' with invalid type id (%zu)",
2177
		 type_name,
2183
		 type_name,
2178
		 type_id);
2184
		 type_id);
2179
      return 0;
2185
      return 0;
Lines 2307-2323 Link Here
2307
  /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2313
  /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2308
  g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2314
  g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2309
  g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2315
  g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2310
  
2316
2317
  /* we only need to lock class_init_rec_mutex if instance_type already has its
2318
   * class initialized, however this function is rarely enough called to take
2319
   * the simple route and always acquire class_init_rec_mutex.
2320
   */
2321
  g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2311
  G_WRITE_LOCK (&type_rw_lock);
2322
  G_WRITE_LOCK (&type_rw_lock);
2312
  if (check_add_interface_L (instance_type, interface_type))
2323
  if (check_add_interface_L (instance_type, interface_type))
2313
    {
2324
    {
2314
      TypeNode *node = lookup_type_node_I (instance_type);
2325
      TypeNode *node = lookup_type_node_I (instance_type);
2315
      TypeNode *iface = lookup_type_node_I (interface_type);
2326
      TypeNode *iface = lookup_type_node_I (interface_type);
2316
      
2317
      if (check_interface_info_I (iface, NODE_TYPE (node), info))
2327
      if (check_interface_info_I (iface, NODE_TYPE (node), info))
2318
        type_add_interface_Wm (node, iface, info, NULL);
2328
        type_add_interface_Wm (node, iface, info, NULL);
2319
    }
2329
    }
2320
  G_WRITE_UNLOCK (&type_rw_lock);
2330
  G_WRITE_UNLOCK (&type_rw_lock);
2331
  g_static_rec_mutex_unlock (&class_init_rec_mutex);
2321
}
2332
}
2322
2333
2323
void
2334
void
Lines 2326-2348 Link Here
2326
			      GTypePlugin *plugin)
2337
			      GTypePlugin *plugin)
2327
{
2338
{
2328
  TypeNode *node;
2339
  TypeNode *node;
2329
  
2330
  /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2340
  /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2331
  g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2341
  g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2332
  g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2342
  g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2333
  
2343
2334
  node = lookup_type_node_I (instance_type);
2344
  node = lookup_type_node_I (instance_type);
2335
  if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
2345
  if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
2336
    return;
2346
    return;
2337
  
2347
2348
  /* see comment in g_type_add_interface_static() about class_init_rec_mutex */
2349
  g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2338
  G_WRITE_LOCK (&type_rw_lock);
2350
  G_WRITE_LOCK (&type_rw_lock);
2339
  if (check_add_interface_L (instance_type, interface_type))
2351
  if (check_add_interface_L (instance_type, interface_type))
2340
    {
2352
    {
2341
      TypeNode *iface = lookup_type_node_I (interface_type);
2353
      TypeNode *iface = lookup_type_node_I (interface_type);
2342
      
2343
      type_add_interface_Wm (node, iface, NULL, plugin);
2354
      type_add_interface_Wm (node, iface, NULL, plugin);
2344
    }
2355
    }
2345
  G_WRITE_UNLOCK (&type_rw_lock);
2356
  G_WRITE_UNLOCK (&type_rw_lock);
2357
  g_static_rec_mutex_unlock (&class_init_rec_mutex);
2346
}
2358
}
2347
2359
2348
2360
Lines 2373-2399 Link Here
2373
		 type_descriptive_name_I (type));
2385
		 type_descriptive_name_I (type));
2374
      return NULL;
2386
      return NULL;
2375
    }
2387
    }
2376
  
2388
2377
  type_data_ref_Wm (node);
2389
  type_data_ref_Wm (node);
2378
  
2390
2379
  if (!node->data->class.class)
2391
  if (!node->data->class.class) /* class uninitialized */
2380
    {
2392
    {
2381
      GType ptype = NODE_PARENT_TYPE (node);
2393
      GType ptype = NODE_PARENT_TYPE (node);
2382
      GTypeClass *pclass = NULL;
2394
      GTypeClass *pclass = NULL;
2383
      
2395
      G_WRITE_UNLOCK (&type_rw_lock);
2396
      g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2384
      if (ptype)
2397
      if (ptype)
2385
	{
2398
        {
2386
	  G_WRITE_UNLOCK (&type_rw_lock);
2399
          pclass = g_type_class_ref (ptype);
2387
	  pclass = g_type_class_ref (ptype);
2400
          G_WRITE_LOCK (&type_rw_lock);
2388
	  if (node->data->class.class)
2401
          node = lookup_type_node_I (type);
2402
          if (node->data->class.class)
2389
            INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
2403
            INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
2390
	  G_WRITE_LOCK (&type_rw_lock);
2404
        }
2391
	}
2405
      else
2392
      
2406
        {
2393
      type_class_init_Wm (node, pclass);
2407
          G_WRITE_LOCK (&type_rw_lock);
2408
          node = lookup_type_node_I (type);
2409
        }
2410
      if (!node->data->class.class) /* class could have been initialized meanwhile */
2411
        type_class_init_Wm (node, pclass);
2412
      G_WRITE_UNLOCK (&type_rw_lock);
2413
      g_static_rec_mutex_unlock (&class_init_rec_mutex);
2394
    }
2414
    }
2395
  G_WRITE_UNLOCK (&type_rw_lock);
2396
  
2397
  return node->data->class.class;
2415
  return node->data->class.class;
2398
}
2416
}
2399
2417
Lines 2409-2415 Link Here
2409
  G_WRITE_LOCK (&type_rw_lock);
2427
  G_WRITE_LOCK (&type_rw_lock);
2410
  if (node && node->is_classed && node->data &&
2428
  if (node && node->is_classed && node->data &&
2411
      node->data->class.class == class && node->data->common.ref_count > 0)
2429
      node->data->class.class == class && node->data->common.ref_count > 0)
2412
    type_data_unref_Wm (node, FALSE);
2430
    type_data_unref_WmREC (node, FALSE);
2413
  else
2431
  else
2414
    g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2432
    g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2415
	       type_descriptive_name_I (class->g_type));
2433
	       type_descriptive_name_I (class->g_type));
Lines 2428-2434 Link Here
2428
  node = lookup_type_node_I (class->g_type);
2446
  node = lookup_type_node_I (class->g_type);
2429
  if (node && node->is_classed && node->data &&
2447
  if (node && node->is_classed && node->data &&
2430
      node->data->class.class == class && node->data->common.ref_count > 0)
2448
      node->data->class.class == class && node->data->common.ref_count > 0)
2431
    type_data_unref_Wm (node, TRUE);
2449
    type_data_unref_WmREC (node, TRUE);
2432
  else
2450
  else
2433
    g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2451
    g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2434
	       type_descriptive_name_I (class->g_type));
2452
	       type_descriptive_name_I (class->g_type));
Lines 2562-2570 Link Here
2562
g_type_default_interface_ref (GType g_type)
2580
g_type_default_interface_ref (GType g_type)
2563
{
2581
{
2564
  TypeNode *node;
2582
  TypeNode *node;
2565
  
2583
  gpointer dflt_vtable;
2584
2566
  G_WRITE_LOCK (&type_rw_lock);
2585
  G_WRITE_LOCK (&type_rw_lock);
2567
  
2586
2568
  node = lookup_type_node_I (g_type);
2587
  node = lookup_type_node_I (g_type);
2569
  if (!node || !NODE_IS_IFACE (node) ||
2588
  if (!node || !NODE_IS_IFACE (node) ||
2570
      (node->data && node->data->common.ref_count < 1))
2589
      (node->data && node->data->common.ref_count < 1))
Lines 2574-2587 Link Here
2574
		 type_descriptive_name_I (g_type));
2593
		 type_descriptive_name_I (g_type));
2575
      return NULL;
2594
      return NULL;
2576
    }
2595
    }
2577
  
2578
  type_data_ref_Wm (node);
2579
2596
2580
  type_iface_ensure_dflt_vtable_Wm (node);
2597
  if (!node->data || !node->data->iface.dflt_vtable)
2598
    {
2599
      G_WRITE_UNLOCK (&type_rw_lock);
2600
      g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2601
      G_WRITE_LOCK (&type_rw_lock);
2602
      node = lookup_type_node_I (g_type);
2603
      type_data_ref_Wm (node);
2604
      type_iface_ensure_dflt_vtable_Wm (node);
2605
      g_static_rec_mutex_unlock (&class_init_rec_mutex);
2606
    }
2607
  else
2608
    type_data_ref_Wm (node); /* ref_count >= 1 already */
2581
2609
2610
  dflt_vtable = node->data->iface.dflt_vtable;
2582
  G_WRITE_UNLOCK (&type_rw_lock);
2611
  G_WRITE_UNLOCK (&type_rw_lock);
2583
  
2612
2584
  return node->data->iface.dflt_vtable;
2613
  return dflt_vtable;
2585
}
2614
}
2586
2615
2587
gpointer
2616
gpointer
Lines 2614-2620 Link Here
2614
  if (node && NODE_IS_IFACE (node) &&
2643
  if (node && NODE_IS_IFACE (node) &&
2615
      node->data->iface.dflt_vtable == g_iface &&
2644
      node->data->iface.dflt_vtable == g_iface &&
2616
      node->data->common.ref_count > 0)
2645
      node->data->common.ref_count > 0)
2617
    type_data_unref_Wm (node, FALSE);
2646
    type_data_unref_WmREC (node, FALSE);
2618
  else
2647
  else
2619
    g_warning ("cannot unreference invalid interface default vtable for '%s'",
2648
    g_warning ("cannot unreference invalid interface default vtable for '%s'",
2620
	       type_descriptive_name_I (vtable->g_type));
2649
	       type_descriptive_name_I (vtable->g_type));
Lines 3336-3342 Link Here
3336
    return vtable;
3365
    return vtable;
3337
  
3366
  
3338
  if (!node)
3367
  if (!node)
3339
    g_warning (G_STRLOC ": type id `%lu' is invalid", type);
3368
    g_warning (G_STRLOC ": type id `%zu' is invalid", type);
3340
  if (!has_refed_data)
3369
  if (!has_refed_data)
3341
    g_warning ("can't peek value table for type `%s' which is not currently referenced",
3370
    g_warning ("can't peek value table for type `%s' which is not currently referenced",
3342
	       type_descriptive_name_I (type));
3371
	       type_descriptive_name_I (type));
Lines 3371-3377 Link Here
3371
  const gchar *env_string;
3400
  const gchar *env_string;
3372
  GTypeInfo info;
3401
  GTypeInfo info;
3373
  TypeNode *node;
3402
  TypeNode *node;
3374
  GType type;
3403
  volatile GType votype;
3375
  
3404
  
3376
  G_LOCK (type_init_lock);
3405
  G_LOCK (type_init_lock);
3377
  
3406
  
Lines 3415-3430 Link Here
3415
  /* void type G_TYPE_NONE
3444
  /* void type G_TYPE_NONE
3416
   */
3445
   */
3417
  node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0);
3446
  node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0);
3418
  type = NODE_TYPE (node);
3447
  votype = NODE_TYPE (node);
3419
  g_assert (type == G_TYPE_NONE);
3448
  g_assert (votype == G_TYPE_NONE);
3420
  
3449
  
3421
  /* interface fundamental type G_TYPE_INTERFACE (!classed)
3450
  /* interface fundamental type G_TYPE_INTERFACE (!classed)
3422
   */
3451
   */
3423
  memset (&info, 0, sizeof (info));
3452
  memset (&info, 0, sizeof (info));
3424
  node = type_node_fundamental_new_W (G_TYPE_INTERFACE, g_intern_static_string ("GInterface"), G_TYPE_FLAG_DERIVABLE);
3453
  node = type_node_fundamental_new_W (G_TYPE_INTERFACE, g_intern_static_string ("GInterface"), G_TYPE_FLAG_DERIVABLE);
3425
  type = NODE_TYPE (node);
3454
  votype = NODE_TYPE (node);
3426
  type_data_make_W (node, &info, NULL);
3455
  type_data_make_W (node, &info, NULL);
3427
  g_assert (type == G_TYPE_INTERFACE);
3456
  g_assert (votype == G_TYPE_INTERFACE);
3428
  
3457
  
3429
  G_WRITE_UNLOCK (&type_rw_lock);
3458
  G_WRITE_UNLOCK (&type_rw_lock);
3430
  
3459
  
Lines 3432-3438 Link Here
3432
3461
3433
  /* G_TYPE_TYPE_PLUGIN
3462
  /* G_TYPE_TYPE_PLUGIN
3434
   */
3463
   */
3435
  g_type_plugin_get_type ();
3464
  votype = g_type_plugin_get_type ();
3436
  
3465
  
3437
  /* G_TYPE_* value types
3466
  /* G_TYPE_* value types
3438
   */
3467
   */

Return to bug 398548