~registry/glib/glib-2-30

« back to all changes in this revision

Viewing changes to gthread/gthread-nspr.c

  • Committer: Owen Taylor
  • Date: 1998-12-15 05:28:02 UTC
  • Revision ID: git-v1:931ea952650b013b834041b91b0c37a748ffd449
This commit merges the glib-threads branch into the main
branch. See the ChangeLog for details of the changes.

In brief overview:

 - The set of threading functions can be set
 - A default implementation is provided in -lgthread
 - All static data structures are locked using these
   functions if g_thread_init() is called.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GLIB - Library of useful routines for C programming
 
2
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
 
3
 *
 
4
 * gthread.c: nspr thread system implementation
 
5
 * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Library General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Library General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Library General Public
 
18
 * License along with this library; if not, write to the
 
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
20
 * Boston, MA 02111-1307, USA.
 
21
 */
 
22
 
 
23
/* 
 
24
 * MT safe
 
25
 */
 
26
 
 
27
#include <prpdce.h>
 
28
#include <prthread.h>
 
29
#include <stdlib.h>
 
30
 
 
31
#ifdef G_DISABLE_ASSERT
 
32
 
 
33
#define STDERR_ASSERT(expr)
 
34
 
 
35
#else /* G_DISABLE_ASSERT */
 
36
 
 
37
#define STDERR_ASSERT(expr)                  G_STMT_START{      \
 
38
     if (!(expr))                                               \
 
39
       g_log (G_LOG_DOMAIN,                                     \
 
40
              G_LOG_LEVEL_ERROR,                                \
 
41
              "file %s: line %d: assertion failed: (%s)",       \
 
42
              __FILE__,                                         \
 
43
              __LINE__,                                         \
 
44
              #expr);                   }G_STMT_END
 
45
 
 
46
#endif /* G_DISABLE_ASSERT */
 
47
 
 
48
/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use
 
49
   functions from gmem.c and gmessages.c; */
 
50
 
 
51
static gboolean
 
52
g_mutex_trylock_nspr_impl (GMutex * mutex)
 
53
{
 
54
  PRStatus status = PRP_TryLock ((PRLock *) mutex);
 
55
  if (status == PR_SUCCESS)
 
56
    {
 
57
      return TRUE;
 
58
    }
 
59
  return FALSE;
 
60
}
 
61
 
 
62
static void
 
63
g_cond_wait_nspr_impl (GCond * cond,
 
64
                       GMutex * entered_mutex)
 
65
{
 
66
  PRStatus status = PRP_NakedWait ((PRCondVar *) cond, 
 
67
                                   (PRLock *) entered_mutex,
 
68
                                   PR_INTERVAL_NO_TIMEOUT);
 
69
  g_assert (status == PR_SUCCESS);
 
70
}
 
71
 
 
72
#define G_MICROSEC 1000000
 
73
 
 
74
static gboolean
 
75
g_cond_timed_wait_nspr_impl (GCond * cond,
 
76
                             GMutex * entered_mutex,
 
77
                             GTimeVal * abs_time)
 
78
{
 
79
  PRStatus status;
 
80
  PRIntervalTime interval;
 
81
  GTimeVal current_time;
 
82
  glong microsecs;
 
83
 
 
84
  g_return_val_if_fail (cond != NULL, FALSE);
 
85
  g_return_val_if_fail (entered_mutex != NULL, FALSE);
 
86
 
 
87
  g_get_current_time (&current_time);
 
88
 
 
89
  if (abs_time->tv_sec < current_time.tv_sec ||
 
90
      (abs_time->tv_sec == current_time.tv_sec &&
 
91
       abs_time->tv_usec < current_time.tv_usec))
 
92
    return FALSE;
 
93
 
 
94
  interval = PR_SecondsToInterval (abs_time->tv_sec - current_time.tv_sec);
 
95
  microsecs = abs_time->tv_usec - current_time.tv_usec;
 
96
  if (microsecs < 0)
 
97
    interval -= PR_MicrosecondsToInterval (-microsecs);
 
98
  else
 
99
    interval += PR_MicrosecondsToInterval (microsecs);
 
100
 
 
101
  status = PRP_NakedWait ((PRCondVar *) cond, (PRLock *) entered_mutex,
 
102
                          interval);
 
103
 
 
104
  g_assert (status == PR_SUCCESS);
 
105
 
 
106
  g_get_current_time (&current_time);
 
107
 
 
108
  if (abs_time->tv_sec < current_time.tv_sec ||
 
109
      (abs_time->tv_sec == current_time.tv_sec &&
 
110
       abs_time->tv_usec < current_time.tv_usec))
 
111
    return FALSE;
 
112
  return TRUE;
 
113
}
 
114
 
 
115
typedef struct _GPrivateNSPRData GPrivateNSPRData;
 
116
struct _GPrivateNSPRData
 
117
  {
 
118
    gpointer data;
 
119
    GDestroyNotify destructor;
 
120
  };
 
121
 
 
122
typedef struct _GPrivateNSPR GPrivateNSPR;
 
123
struct _GPrivateNSPR
 
124
  {
 
125
    PRUintn private;
 
126
    GDestroyNotify destructor;
 
127
  };
 
128
 
 
129
static GPrivateNSPRData *
 
130
g_private_nspr_data_constructor (GDestroyNotify destructor, gpointer data)
 
131
{
 
132
  /* we can not use g_new and friends, as they might use private data by
 
133
     themself */
 
134
  GPrivateNSPRData *private = malloc (sizeof (GPrivateNSPRData));
 
135
  g_assert (private);
 
136
  private->data = data;
 
137
  private->destructor = destructor;
 
138
 
 
139
  return private;
 
140
}
 
141
 
 
142
static void
 
143
g_private_nspr_data_destructor (gpointer data)
 
144
{
 
145
  GPrivateNSPRData *private = data;
 
146
  if (private->destructor && private->data)
 
147
    (*private->destructor) (private->data);
 
148
  free (private);
 
149
}
 
150
 
 
151
static GPrivate *
 
152
g_private_new_nspr_impl (GDestroyNotify destructor)
 
153
{
 
154
  GPrivateNSPR *result = g_new (GPrivateNSPR, 1);
 
155
  PRStatus status = PR_NewThreadPrivateIndex (&result->private,
 
156
                                            g_private_nspr_data_destructor);
 
157
  g_assert (status == PR_SUCCESS);
 
158
 
 
159
  result->destructor = destructor;
 
160
  return (GPrivate *) result;
 
161
}
 
162
 
 
163
/* NOTE: the functions g_private_get and g_private_set may not use
 
164
   functions from gmem.c and gmessages.c */
 
165
 
 
166
static GPrivateNSPRData *
 
167
g_private_nspr_data_get (GPrivateNSPR * private)
 
168
{
 
169
  GPrivateNSPRData *data;
 
170
 
 
171
  STDERR_ASSERT (private);
 
172
 
 
173
  data = PR_GetThreadPrivate (private->private);
 
174
  if (!data)
 
175
    {
 
176
      data = g_private_nspr_data_constructor (private->destructor, NULL);
 
177
      STDERR_ASSERT (PR_SetThreadPrivate (private->private, data)
 
178
                     == PR_SUCCESS);
 
179
    }
 
180
 
 
181
  return data;
 
182
}
 
183
 
 
184
static void
 
185
g_private_set_nspr_impl (GPrivate * private, gpointer value)
 
186
{
 
187
  if (!private)
 
188
    return;
 
189
 
 
190
  g_private_nspr_data_get ((GPrivateNSPR *) private)->data = value;
 
191
}
 
192
 
 
193
static gpointer
 
194
g_private_get_nspr_impl (GPrivate * private)
 
195
{
 
196
  if (!private)
 
197
    return NULL;
 
198
 
 
199
  return g_private_nspr_data_get ((GPrivateNSPR *) private)->data;
 
200
}
 
201
 
 
202
static GThreadFunctions g_thread_functions_for_glib_use_default =
 
203
{
 
204
  (GMutex * (*)())PR_NewLock,
 
205
  (void (*)(GMutex *)) PR_Lock,
 
206
  g_mutex_trylock_nspr_impl,
 
207
  (void (*)(GMutex *)) PR_Unlock,
 
208
  (void (*)(GMutex *)) PR_DestroyLock,
 
209
  (GCond * (*)())PRP_NewNakedCondVar,
 
210
  (void (*)(GCond *)) PRP_NakedNotify,
 
211
  (void (*)(GCond *)) PRP_NakedBroadcast,
 
212
  g_cond_wait_nspr_impl,
 
213
  g_cond_timed_wait_nspr_impl,
 
214
  (void (*)(GCond *)) PRP_DestroyNakedCondVar,
 
215
  g_private_new_nspr_impl,
 
216
  g_private_get_nspr_impl,
 
217
  g_private_set_nspr_impl
 
218
};