mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 23:16:14 +01:00
Add regression test for GWeakRef used to cache a singleton
https://bugzilla.gnome.org/show_bug.cgi?id=548954
This commit is contained in:
parent
fa5ff39559
commit
146aa7aa17
@ -204,6 +204,126 @@ test_threaded_object_init (void)
|
||||
g_thread_join (creator);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
MyTester0 *strong;
|
||||
guint unref_delay;
|
||||
} UnrefInThreadData;
|
||||
|
||||
static gpointer
|
||||
unref_in_thread (gpointer p)
|
||||
{
|
||||
UnrefInThreadData *data = p;
|
||||
|
||||
g_usleep (data->unref_delay);
|
||||
g_object_unref (data->strong);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* undefine to see this test fail without GWeakRef */
|
||||
#define HAVE_G_WEAK_REF
|
||||
|
||||
#define SLEEP_MIN_USEC 1
|
||||
#define SLEEP_MAX_USEC 10
|
||||
|
||||
static void
|
||||
test_threaded_weak_ref (void)
|
||||
{
|
||||
guint i;
|
||||
guint get_wins = 0, unref_wins = 0;
|
||||
guint n;
|
||||
|
||||
if (g_test_thorough ())
|
||||
n = NUM_COUNTER_INCREMENTS;
|
||||
else
|
||||
n = NUM_COUNTER_INCREMENTS / 20;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
UnrefInThreadData data;
|
||||
#ifdef HAVE_G_WEAK_REF
|
||||
/* GWeakRef<MyTester0> in C++ terms */
|
||||
GWeakRef weak;
|
||||
#else
|
||||
gpointer weak;
|
||||
#endif
|
||||
MyTester0 *strengthened;
|
||||
guint get_delay;
|
||||
GThread *thread;
|
||||
GError *error = NULL;
|
||||
|
||||
if (g_test_verbose () && (i % (n/20)) == 0)
|
||||
g_print ("%u%%\n", ((i * 100) / n));
|
||||
|
||||
/* Have an object and a weak ref to it */
|
||||
data.strong = g_object_new (my_tester0_get_type (), NULL);
|
||||
|
||||
#ifdef HAVE_G_WEAK_REF
|
||||
g_weak_ref_init (&weak, data.strong);
|
||||
#else
|
||||
weak = data.strong;
|
||||
g_object_add_weak_pointer ((GObject *) weak, &weak);
|
||||
#endif
|
||||
|
||||
/* Delay for a random time on each side of the race, to perturb the
|
||||
* timing. Ideally, we want each side to win half the races; on
|
||||
* smcv's laptop, these timings are about right.
|
||||
*/
|
||||
data.unref_delay = g_random_int_range (SLEEP_MIN_USEC / 2, SLEEP_MAX_USEC / 2);
|
||||
get_delay = g_random_int_range (SLEEP_MIN_USEC, SLEEP_MAX_USEC);
|
||||
|
||||
/* One half of the race is to unref the shared object */
|
||||
thread = g_thread_create (unref_in_thread, &data, TRUE, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* The other half of the race is to get the object from the "global
|
||||
* singleton"
|
||||
*/
|
||||
g_usleep (get_delay);
|
||||
|
||||
#ifdef HAVE_G_WEAK_REF
|
||||
strengthened = g_weak_ref_get (&weak);
|
||||
#else
|
||||
/* Spot the unsafe pointer access! In GDBusConnection this is rather
|
||||
* better-hidden, but ends up with essentially the same thing, albeit
|
||||
* cleared in dispose() rather than by a traditional weak pointer
|
||||
*/
|
||||
strengthened = weak;
|
||||
|
||||
if (strengthened != NULL)
|
||||
g_object_ref (strengthened);
|
||||
#endif
|
||||
|
||||
if (strengthened != NULL)
|
||||
g_assert (G_IS_OBJECT (strengthened));
|
||||
|
||||
/* Wait for the thread to run */
|
||||
g_thread_join (thread);
|
||||
|
||||
if (strengthened != NULL)
|
||||
{
|
||||
get_wins++;
|
||||
g_assert (G_IS_OBJECT (strengthened));
|
||||
g_object_unref (strengthened);
|
||||
}
|
||||
else
|
||||
{
|
||||
unref_wins++;
|
||||
}
|
||||
|
||||
#ifdef HAVE_G_WEAK_REF
|
||||
g_weak_ref_clear (&weak);
|
||||
#else
|
||||
if (weak != NULL)
|
||||
g_object_remove_weak_pointer (weak, &weak);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Race won by get %u times, unref %u times\n",
|
||||
get_wins, unref_wins);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -213,6 +333,7 @@ main (int argc,
|
||||
|
||||
g_test_add_func ("/GObject/threaded-class-init", test_threaded_class_init);
|
||||
g_test_add_func ("/GObject/threaded-object-init", test_threaded_object_init);
|
||||
g_test_add_func ("/GObject/threaded-weak-ref", test_threaded_weak_ref);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user