Blame glib/tests/atomic.c

Packit ae235b
/*
Packit ae235b
 * Copyright 2011 Red Hat, Inc.
Packit ae235b
 *
Packit ae235b
 * This program is free software; you can redistribute it and/or
Packit ae235b
 * modify it under the terms of the GNU Lesser General Public
Packit ae235b
 * License as published by the Free Software Foundation; either
Packit ae235b
 * version 2.1 of the License, or (at your option) any later version.
Packit ae235b
 *
Packit ae235b
 * See the included COPYING file for more information.
Packit ae235b
 */
Packit ae235b
Packit ae235b
#include <glib.h>
Packit ae235b
Packit ae235b
static void
Packit ae235b
test_types (void)
Packit ae235b
{
Packit ae235b
  const gint *csp;
Packit ae235b
  const gint * const *cspp;
Packit ae235b
  guint u, u2;
Packit ae235b
  gint s, s2;
Packit ae235b
  gpointer vp, vp2;
Packit ae235b
  int *ip, *ip2;
Packit ae235b
  gsize gs, gs2;
Packit ae235b
  gboolean res;
Packit ae235b
Packit ae235b
  csp = &s;
Packit ae235b
  cspp = &csp;
Packit ae235b
Packit ae235b
  g_atomic_int_set (&u, 5);
Packit ae235b
  u2 = g_atomic_int_get (&u);
Packit ae235b
  g_assert_cmpint (u2, ==, 5);
Packit ae235b
  res = g_atomic_int_compare_and_exchange (&u, 6, 7);
Packit ae235b
  g_assert (!res);
Packit ae235b
  g_assert_cmpint (u, ==, 5);
Packit ae235b
  g_atomic_int_add (&u, 1);
Packit ae235b
  g_assert_cmpint (u, ==, 6);
Packit ae235b
  g_atomic_int_inc (&u);
Packit ae235b
  g_assert_cmpint (u, ==, 7);
Packit ae235b
  res = g_atomic_int_dec_and_test (&u);
Packit ae235b
  g_assert (!res);
Packit ae235b
  g_assert_cmpint (u, ==, 6);
Packit ae235b
  u2 = g_atomic_int_and (&u, 5);
Packit ae235b
  g_assert_cmpint (u2, ==, 6);
Packit ae235b
  g_assert_cmpint (u, ==, 4);
Packit ae235b
  u2 = g_atomic_int_or (&u, 8);
Packit ae235b
  g_assert_cmpint (u2, ==, 4);
Packit ae235b
  g_assert_cmpint (u, ==, 12);
Packit ae235b
  u2 = g_atomic_int_xor (&u, 4);
Packit ae235b
  g_assert_cmpint (u2, ==, 12);
Packit ae235b
  g_assert_cmpint (u, ==, 8);
Packit ae235b
Packit ae235b
  g_atomic_int_set (&s, 5);
Packit ae235b
  s2 = g_atomic_int_get (&s);
Packit ae235b
  g_assert_cmpint (s2, ==, 5);
Packit ae235b
  res = g_atomic_int_compare_and_exchange (&s, 6, 7);
Packit ae235b
  g_assert (!res);
Packit ae235b
  g_assert_cmpint (s, ==, 5);
Packit ae235b
  g_atomic_int_add (&s, 1);
Packit ae235b
  g_assert_cmpint (s, ==, 6);
Packit ae235b
  g_atomic_int_inc (&s);
Packit ae235b
  g_assert_cmpint (s, ==, 7);
Packit ae235b
  res = g_atomic_int_dec_and_test (&s);
Packit ae235b
  g_assert (!res);
Packit ae235b
  g_assert_cmpint (s, ==, 6);
Packit ae235b
  s2 = g_atomic_int_and (&s, 5);
Packit ae235b
  g_assert_cmpint (s2, ==, 6);
Packit ae235b
  g_assert_cmpint (s, ==, 4);
Packit ae235b
  s2 = g_atomic_int_or (&s, 8);
Packit ae235b
  g_assert_cmpint (s2, ==, 4);
Packit ae235b
  g_assert_cmpint (s, ==, 12);
Packit ae235b
  s2 = g_atomic_int_xor (&s, 4);
Packit ae235b
  g_assert_cmpint (s2, ==, 12);
Packit ae235b
  g_assert_cmpint (s, ==, 8);
Packit ae235b
Packit ae235b
  g_atomic_pointer_set (&vp, 0);
Packit ae235b
  vp2 = g_atomic_pointer_get (&vp);
Packit ae235b
  g_assert (vp2 == 0);
Packit ae235b
  res = g_atomic_pointer_compare_and_exchange (&vp, 0, 0);
Packit ae235b
  g_assert (res);
Packit ae235b
  g_assert (vp == 0);
Packit ae235b
Packit ae235b
  g_atomic_pointer_set (&ip, 0);
Packit ae235b
  ip2 = g_atomic_pointer_get (&ip);
Packit ae235b
  g_assert (ip2 == 0);
Packit ae235b
  res = g_atomic_pointer_compare_and_exchange (&ip, 0, 0);
Packit ae235b
  g_assert (res);
Packit ae235b
  g_assert (ip == 0);
Packit ae235b
Packit ae235b
  g_atomic_pointer_set (&gs, 0);
Packit ae235b
  gs2 = (gsize) g_atomic_pointer_get (&gs);
Packit ae235b
  g_assert (gs2 == 0);
Packit ae235b
  res = g_atomic_pointer_compare_and_exchange (&gs, 0, 0);
Packit ae235b
  g_assert (res);
Packit ae235b
  g_assert (gs == 0);
Packit ae235b
  gs2 = g_atomic_pointer_add (&gs, 5);
Packit ae235b
  g_assert (gs2 == 0);
Packit ae235b
  g_assert (gs == 5);
Packit ae235b
  gs2 = g_atomic_pointer_and (&gs, 6);
Packit ae235b
  g_assert (gs2 == 5);
Packit ae235b
  g_assert (gs == 4);
Packit ae235b
  gs2 = g_atomic_pointer_or (&gs, 8);
Packit ae235b
  g_assert (gs2 == 4);
Packit ae235b
  g_assert (gs == 12);
Packit ae235b
  gs2 = g_atomic_pointer_xor (&gs, 4);
Packit ae235b
  g_assert (gs2 == 12);
Packit ae235b
  g_assert (gs == 8);
Packit ae235b
Packit ae235b
  g_assert (g_atomic_int_get (csp) == s);
Packit ae235b
  g_assert (g_atomic_pointer_get (cspp) == csp);
Packit ae235b
Packit ae235b
  /* repeat, without the macros */
Packit ae235b
#undef g_atomic_int_set
Packit ae235b
#undef g_atomic_int_get
Packit ae235b
#undef g_atomic_int_compare_and_exchange
Packit ae235b
#undef g_atomic_int_add
Packit ae235b
#undef g_atomic_int_inc
Packit ae235b
#undef g_atomic_int_and
Packit ae235b
#undef g_atomic_int_or
Packit ae235b
#undef g_atomic_int_xor
Packit ae235b
#undef g_atomic_int_dec_and_test
Packit ae235b
#undef g_atomic_pointer_set
Packit ae235b
#undef g_atomic_pointer_get
Packit ae235b
#undef g_atomic_pointer_compare_and_exchange
Packit ae235b
#undef g_atomic_pointer_add
Packit ae235b
#undef g_atomic_pointer_and
Packit ae235b
#undef g_atomic_pointer_or
Packit ae235b
#undef g_atomic_pointer_xor
Packit ae235b
Packit ae235b
  g_atomic_int_set ((gint*)&u, 5);
Packit ae235b
  u2 = g_atomic_int_get ((gint*)&u);
Packit ae235b
  g_assert_cmpint (u2, ==, 5);
Packit ae235b
  res = g_atomic_int_compare_and_exchange ((gint*)&u, 6, 7);
Packit ae235b
  g_assert (!res);
Packit ae235b
  g_assert_cmpint (u, ==, 5);
Packit ae235b
  g_atomic_int_add ((gint*)&u, 1);
Packit ae235b
  g_assert_cmpint (u, ==, 6);
Packit ae235b
  g_atomic_int_inc ((gint*)&u);
Packit ae235b
  g_assert_cmpint (u, ==, 7);
Packit ae235b
  res = g_atomic_int_dec_and_test ((gint*)&u);
Packit ae235b
  g_assert (!res);
Packit ae235b
  g_assert_cmpint (u, ==, 6);
Packit ae235b
  u2 = g_atomic_int_and (&u, 5);
Packit ae235b
  g_assert_cmpint (u2, ==, 6);
Packit ae235b
  g_assert_cmpint (u, ==, 4);
Packit ae235b
  u2 = g_atomic_int_or (&u, 8);
Packit ae235b
  g_assert_cmpint (u2, ==, 4);
Packit ae235b
  g_assert_cmpint (u, ==, 12);
Packit ae235b
  u2 = g_atomic_int_xor (&u, 4);
Packit ae235b
  g_assert_cmpint (u2, ==, 12);
Packit ae235b
Packit ae235b
  g_atomic_int_set (&s, 5);
Packit ae235b
  s2 = g_atomic_int_get (&s);
Packit ae235b
  g_assert_cmpint (s2, ==, 5);
Packit ae235b
  res = g_atomic_int_compare_and_exchange (&s, 6, 7);
Packit ae235b
  g_assert (!res);
Packit ae235b
  g_assert_cmpint (s, ==, 5);
Packit ae235b
  g_atomic_int_add (&s, 1);
Packit ae235b
  g_assert_cmpint (s, ==, 6);
Packit ae235b
  g_atomic_int_inc (&s);
Packit ae235b
  g_assert_cmpint (s, ==, 7);
Packit ae235b
  res = g_atomic_int_dec_and_test (&s);
Packit ae235b
  g_assert (!res);
Packit ae235b
  g_assert_cmpint (s, ==, 6);
Packit ae235b
  s2 = g_atomic_int_and ((guint*)&s, 5);
Packit ae235b
  g_assert_cmpint (s2, ==, 6);
Packit ae235b
  g_assert_cmpint (s, ==, 4);
Packit ae235b
  s2 = g_atomic_int_or ((guint*)&s, 8);
Packit ae235b
  g_assert_cmpint (s2, ==, 4);
Packit ae235b
  g_assert_cmpint (s, ==, 12);
Packit ae235b
  s2 = g_atomic_int_xor ((guint*)&s, 4);
Packit ae235b
  g_assert_cmpint (s2, ==, 12);
Packit ae235b
  g_assert_cmpint (s, ==, 8);
Packit ae235b
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
Packit ae235b
  s2 = g_atomic_int_exchange_and_add ((gint*)&s, 1);
Packit ae235b
G_GNUC_END_IGNORE_DEPRECATIONS
Packit ae235b
  g_assert_cmpint (s2, ==, 8);
Packit ae235b
  g_assert_cmpint (s, ==, 9);
Packit ae235b
Packit ae235b
  g_atomic_pointer_set (&vp, 0);
Packit ae235b
  vp2 = g_atomic_pointer_get (&vp);
Packit ae235b
  g_assert (vp2 == 0);
Packit ae235b
  res = g_atomic_pointer_compare_and_exchange (&vp, 0, 0);
Packit ae235b
  g_assert (res);
Packit ae235b
  g_assert (vp == 0);
Packit ae235b
Packit ae235b
  g_atomic_pointer_set (&ip, 0);
Packit ae235b
  ip2 = g_atomic_pointer_get (&ip);
Packit ae235b
  g_assert (ip2 == 0);
Packit ae235b
  res = g_atomic_pointer_compare_and_exchange (&ip, 0, 0);
Packit ae235b
  g_assert (res);
Packit ae235b
  g_assert (ip == 0);
Packit ae235b
Packit ae235b
  g_atomic_pointer_set (&gs, 0);
Packit ae235b
  gs2 = (gsize) g_atomic_pointer_get (&gs);
Packit ae235b
  g_assert (gs2 == 0);
Packit ae235b
  res = g_atomic_pointer_compare_and_exchange (&gs, 0, 0);
Packit ae235b
  g_assert (res);
Packit ae235b
  g_assert (gs == 0);
Packit ae235b
  gs2 = g_atomic_pointer_add (&gs, 5);
Packit ae235b
  g_assert (gs2 == 0);
Packit ae235b
  g_assert (gs == 5);
Packit ae235b
  gs2 = g_atomic_pointer_and (&gs, 6);
Packit ae235b
  g_assert (gs2 == 5);
Packit ae235b
  g_assert (gs == 4);
Packit ae235b
  gs2 = g_atomic_pointer_or (&gs, 8);
Packit ae235b
  g_assert (gs2 == 4);
Packit ae235b
  g_assert (gs == 12);
Packit ae235b
  gs2 = g_atomic_pointer_xor (&gs, 4);
Packit ae235b
  g_assert (gs2 == 12);
Packit ae235b
  g_assert (gs == 8);
Packit ae235b
Packit ae235b
  g_assert (g_atomic_int_get (csp) == s);
Packit ae235b
  g_assert (g_atomic_pointer_get (cspp) == csp);
Packit ae235b
}
Packit ae235b
Packit ae235b
#define THREADS 10
Packit ae235b
#define ROUNDS 10000
Packit ae235b
Packit ae235b
volatile gint bucket[THREADS];
Packit ae235b
volatile gint atomic;
Packit ae235b
Packit ae235b
static gpointer
Packit ae235b
thread_func (gpointer data)
Packit ae235b
{
Packit ae235b
  gint idx = GPOINTER_TO_INT (data);
Packit ae235b
  gint i;
Packit ae235b
  gint d;
Packit ae235b
Packit ae235b
  for (i = 0; i < ROUNDS; i++)
Packit ae235b
    {
Packit ae235b
      d = g_random_int_range (-10, 100);
Packit ae235b
      bucket[idx] += d;
Packit ae235b
      g_atomic_int_add (&atomic, d);
Packit ae235b
      g_thread_yield ();
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return NULL;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
test_threaded (void)
Packit ae235b
{
Packit ae235b
  gint sum;
Packit ae235b
  gint i;
Packit ae235b
  GThread *threads[THREADS];
Packit ae235b
Packit ae235b
  atomic = 0;
Packit ae235b
  for (i = 0; i < THREADS; i++)
Packit ae235b
    bucket[i] = 0;
Packit ae235b
Packit ae235b
  for (i = 0; i < THREADS; i++)
Packit ae235b
    threads[i] = g_thread_new ("atomic", thread_func, GINT_TO_POINTER (i));
Packit ae235b
Packit ae235b
  for (i = 0; i < THREADS; i++)
Packit ae235b
    g_thread_join (threads[i]);
Packit ae235b
Packit ae235b
  sum = 0;
Packit ae235b
  for (i = 0; i < THREADS; i++)
Packit ae235b
    sum += bucket[i];
Packit ae235b
Packit ae235b
  g_assert_cmpint (sum, ==, atomic);
Packit ae235b
}
Packit ae235b
Packit ae235b
int
Packit ae235b
main (int argc, char **argv)
Packit ae235b
{
Packit ae235b
  g_test_init (&argc, &argv, NULL);
Packit ae235b
Packit ae235b
  g_test_add_func ("/atomic/types", test_types);
Packit ae235b
  g_test_add_func ("/atomic/threaded", test_threaded);
Packit ae235b
Packit ae235b
  return g_test_run ();
Packit ae235b
}