mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
2c30e8620f
1998-12-15 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * Makefile.am (EXTRA_DIST): updated. * testgthread.c, gthread-*.c: Changed private to private_key to avoid problems when compiling with under C++.
219 lines
5.9 KiB
C
219 lines
5.9 KiB
C
/* GLIB - Library of useful routines for C programming
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
*
|
|
* gthread.c: nspr thread system implementation
|
|
* Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/*
|
|
* MT safe
|
|
*/
|
|
|
|
#include <prpdce.h>
|
|
#include <prthread.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifdef G_DISABLE_ASSERT
|
|
|
|
#define STDERR_ASSERT(expr)
|
|
|
|
#else /* G_DISABLE_ASSERT */
|
|
|
|
#define STDERR_ASSERT(expr) G_STMT_START{ \
|
|
if (!(expr)) \
|
|
g_log (G_LOG_DOMAIN, \
|
|
G_LOG_LEVEL_ERROR, \
|
|
"file %s: line %d: assertion failed: (%s)", \
|
|
__FILE__, \
|
|
__LINE__, \
|
|
#expr); }G_STMT_END
|
|
|
|
#endif /* G_DISABLE_ASSERT */
|
|
|
|
/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use
|
|
functions from gmem.c and gmessages.c; */
|
|
|
|
static gboolean
|
|
g_mutex_trylock_nspr_impl (GMutex * mutex)
|
|
{
|
|
PRStatus status = PRP_TryLock ((PRLock *) mutex);
|
|
if (status == PR_SUCCESS)
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
g_cond_wait_nspr_impl (GCond * cond,
|
|
GMutex * entered_mutex)
|
|
{
|
|
PRStatus status = PRP_NakedWait ((PRCondVar *) cond,
|
|
(PRLock *) entered_mutex,
|
|
PR_INTERVAL_NO_TIMEOUT);
|
|
g_assert (status == PR_SUCCESS);
|
|
}
|
|
|
|
#define G_MICROSEC 1000000
|
|
|
|
static gboolean
|
|
g_cond_timed_wait_nspr_impl (GCond * cond,
|
|
GMutex * entered_mutex,
|
|
GTimeVal * abs_time)
|
|
{
|
|
PRStatus status;
|
|
PRIntervalTime interval;
|
|
GTimeVal current_time;
|
|
glong microsecs;
|
|
|
|
g_return_val_if_fail (cond != NULL, FALSE);
|
|
g_return_val_if_fail (entered_mutex != NULL, FALSE);
|
|
|
|
g_get_current_time (¤t_time);
|
|
|
|
if (abs_time->tv_sec < current_time.tv_sec ||
|
|
(abs_time->tv_sec == current_time.tv_sec &&
|
|
abs_time->tv_usec < current_time.tv_usec))
|
|
return FALSE;
|
|
|
|
interval = PR_SecondsToInterval (abs_time->tv_sec - current_time.tv_sec);
|
|
microsecs = abs_time->tv_usec - current_time.tv_usec;
|
|
if (microsecs < 0)
|
|
interval -= PR_MicrosecondsToInterval (-microsecs);
|
|
else
|
|
interval += PR_MicrosecondsToInterval (microsecs);
|
|
|
|
status = PRP_NakedWait ((PRCondVar *) cond, (PRLock *) entered_mutex,
|
|
interval);
|
|
|
|
g_assert (status == PR_SUCCESS);
|
|
|
|
g_get_current_time (¤t_time);
|
|
|
|
if (abs_time->tv_sec < current_time.tv_sec ||
|
|
(abs_time->tv_sec == current_time.tv_sec &&
|
|
abs_time->tv_usec < current_time.tv_usec))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
typedef struct _GPrivateNSPRData GPrivateNSPRData;
|
|
struct _GPrivateNSPRData
|
|
{
|
|
gpointer data;
|
|
GDestroyNotify destructor;
|
|
};
|
|
|
|
typedef struct _GPrivateNSPR GPrivateNSPR;
|
|
struct _GPrivateNSPR
|
|
{
|
|
PRUintn private_key;
|
|
GDestroyNotify destructor;
|
|
};
|
|
|
|
static GPrivateNSPRData *
|
|
g_private_nspr_data_constructor (GDestroyNotify destructor, gpointer data)
|
|
{
|
|
/* we can not use g_new and friends, as they might use private data by
|
|
themself */
|
|
GPrivateNSPRData *private_key = malloc (sizeof (GPrivateNSPRData));
|
|
g_assert (private_key);
|
|
private_key->data = data;
|
|
private_key->destructor = destructor;
|
|
|
|
return private_key;
|
|
}
|
|
|
|
static void
|
|
g_private_nspr_data_destructor (gpointer data)
|
|
{
|
|
GPrivateNSPRData *private_key = data;
|
|
if (private_key->destructor && private_key->data)
|
|
(*private_key->destructor) (private_key->data);
|
|
free (private_key);
|
|
}
|
|
|
|
static GPrivate *
|
|
g_private_new_nspr_impl (GDestroyNotify destructor)
|
|
{
|
|
GPrivateNSPR *result = g_new (GPrivateNSPR, 1);
|
|
PRStatus status = PR_NewThreadPrivateIndex (&result->private_key,
|
|
g_private_nspr_data_destructor);
|
|
g_assert (status == PR_SUCCESS);
|
|
|
|
result->destructor = destructor;
|
|
return (GPrivate *) result;
|
|
}
|
|
|
|
/* NOTE: the functions g_private_get and g_private_set may not use
|
|
functions from gmem.c and gmessages.c */
|
|
|
|
static GPrivateNSPRData *
|
|
g_private_nspr_data_get (GPrivateNSPR * private_key)
|
|
{
|
|
GPrivateNSPRData *data;
|
|
|
|
STDERR_ASSERT (private_key);
|
|
|
|
data = PR_GetThreadPrivate (private_key->private_key);
|
|
if (!data)
|
|
{
|
|
data = g_private_nspr_data_constructor (private_key->destructor, NULL);
|
|
STDERR_ASSERT (PR_SetThreadPrivate (private_key->private_key, data)
|
|
== PR_SUCCESS);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
static void
|
|
g_private_set_nspr_impl (GPrivate * private_key, gpointer value)
|
|
{
|
|
if (!private_key)
|
|
return;
|
|
|
|
g_private_nspr_data_get ((GPrivateNSPR *) private_key)->data = value;
|
|
}
|
|
|
|
static gpointer
|
|
g_private_get_nspr_impl (GPrivate * private_key)
|
|
{
|
|
if (!private_key)
|
|
return NULL;
|
|
|
|
return g_private_nspr_data_get ((GPrivateNSPR *) private_key)->data;
|
|
}
|
|
|
|
static GThreadFunctions g_thread_functions_for_glib_use_default =
|
|
{
|
|
(GMutex * (*)())PR_NewLock,
|
|
(void (*)(GMutex *)) PR_Lock,
|
|
g_mutex_trylock_nspr_impl,
|
|
(void (*)(GMutex *)) PR_Unlock,
|
|
(void (*)(GMutex *)) PR_DestroyLock,
|
|
(GCond * (*)())PRP_NewNakedCondVar,
|
|
(void (*)(GCond *)) PRP_NakedNotify,
|
|
(void (*)(GCond *)) PRP_NakedBroadcast,
|
|
g_cond_wait_nspr_impl,
|
|
g_cond_timed_wait_nspr_impl,
|
|
(void (*)(GCond *)) PRP_DestroyNakedCondVar,
|
|
g_private_new_nspr_impl,
|
|
g_private_get_nspr_impl,
|
|
g_private_set_nspr_impl
|
|
};
|