~ubuntu-branches/ubuntu/lucid/pdl/lucid

« back to all changes in this revision

Viewing changes to Basic/Core/pdlmagic.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Gertzfield
  • Date: 2002-04-08 18:47:16 UTC
  • Revision ID: james.westby@ubuntu.com-20020408184716-0hf64dc96kin3htp
Tags: upstream-2.3.2
ImportĀ upstreamĀ versionĀ 2.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define PDL_CORE      /* For certain ifdefs */
 
2
#ifndef WIN32
 
3
#define USE_MMAP
 
4
#else
 
5
#undef USE_MMAP
 
6
#endif
 
7
 
 
8
#include "pdlcore.h"
 
9
 
 
10
/* Singly linked list */
 
11
/* Note that this zeroes ->next!) */
 
12
 
 
13
void pdl__magic_add(pdl *it,pdl_magic *mag)
 
14
{
 
15
        pdl_magic **foo = &(it->magic);
 
16
        while(*foo) {
 
17
                foo = &((*foo)->next);
 
18
        }
 
19
        (*foo) = mag;
 
20
        mag->next = NULL;
 
21
}
 
22
 
 
23
void pdl__magic_rm(pdl *it,pdl_magic *mag)
 
24
{
 
25
        pdl_magic **foo = &(it->magic);
 
26
        while(*foo) {
 
27
                if(*foo == mag) {
 
28
                        *foo = (*foo)->next;
 
29
                }
 
30
                foo = &((*foo)->next);
 
31
        }
 
32
        die("PDL:Magic not found: Internal error\n");
 
33
}
 
34
 
 
35
/* Test for undestroyability */
 
36
 
 
37
int pdl__magic_isundestroyable(pdl *it)
 
38
{
 
39
        pdl_magic **foo = &(it->magic);
 
40
        while(*foo) {
 
41
                if((*foo)->what & PDL_MAGIC_UNDESTROYABLE) {return 1;}
 
42
                foo = &((*foo)->next);
 
43
        }
 
44
        return 0;
 
45
}
 
46
 
 
47
/* Call magics */
 
48
 
 
49
void *pdl__call_magic(pdl *it,int which)
 
50
{
 
51
        void *ret = NULL;
 
52
        pdl_magic **foo = &(it->magic);
 
53
        while(*foo) {
 
54
                if((*foo)->what & which) {
 
55
                        if((*foo)->what & PDL_MAGIC_DELAYED)
 
56
                                pdl_add_delayed_magic(*foo);
 
57
                        else
 
58
                                ret = (void *)((*foo)->vtable->cast(*foo));
 
59
                                        /* Cast spell */
 
60
                }
 
61
                foo = &((*foo)->next);
 
62
        }
 
63
        return ret;
 
64
}
 
65
 
 
66
/* XXX FINDS ONLY FIRST */
 
67
pdl_magic *pdl__find_magic(pdl *it, int which)
 
68
{
 
69
        pdl_magic **foo = &(it->magic);
 
70
        while(*foo) {
 
71
                if((*foo)->what & which) {
 
72
                        return *foo;
 
73
                }
 
74
                foo = &((*foo)->next);
 
75
        }
 
76
        return NULL;
 
77
}
 
78
 
 
79
pdl_magic *pdl__print_magic(pdl *it)
 
80
{
 
81
        pdl_magic **foo = &(it->magic);
 
82
        while(*foo) {
 
83
          printf("Magic %d\ttype: ",*foo);
 
84
                if((*foo)->what & PDL_MAGIC_MARKCHANGED)
 
85
                  printf("PDL_MAGIC_MARKCHANGED");
 
86
                else if ((*foo)->what & PDL_MAGIC_MUTATEDPARENT)
 
87
                  printf("PDL_MAGIC_MUTATEDPARENT");
 
88
                else if ((*foo)->what & PDL_MAGIC_THREADING)
 
89
                  printf("PDL_MAGIC_THREADING");
 
90
                else
 
91
                  printf("UNKNOWN");
 
92
                if ((*foo)->what & (PDL_MAGIC_DELAYED|PDL_MAGIC_UNDESTROYABLE))
 
93
                  {
 
94
                    printf(" qualifier(s): ");
 
95
                    if ((*foo)->what & PDL_MAGIC_DELAYED)
 
96
                      printf(" PDL_MAGIC_DELAYED");
 
97
                    if ((*foo)->what & PDL_MAGIC_UNDESTROYABLE)
 
98
                      printf(" PDL_MAGIC_UNDESTROYABLE");
 
99
                  }
 
100
                printf("\n");
 
101
                foo = &((*foo)->next);
 
102
        }
 
103
        return NULL;
 
104
}
 
105
 
 
106
 
 
107
int pdl__ismagic(pdl *it)
 
108
{
 
109
        return (it->magic != 0);
 
110
}
 
111
 
 
112
static pdl_magic **delayed=NULL;
 
113
static int ndelayed = 0;
 
114
void pdl_add_delayed_magic(pdl_magic *mag) {
 
115
        delayed = realloc(delayed,sizeof(*delayed)*++ndelayed);
 
116
        delayed[ndelayed-1] = mag;
 
117
}
 
118
void pdl_run_delayed_magic() {
 
119
        int i;
 
120
        pdl_magic **oldd = delayed; /* In case someone makes new delayed stuff */
 
121
        int nold = ndelayed;
 
122
        delayed = NULL;
 
123
        ndelayed = 0;
 
124
        for(i=0; i<nold; i++) {
 
125
                oldd[i]->vtable->cast(oldd[i]);
 
126
        }
 
127
        free(oldd);
 
128
}
 
129
 
 
130
/****************
 
131
 *
 
132
 * ->bind - magic
 
133
 */
 
134
 
 
135
void *svmagic_cast(pdl_magic *mag)
 
136
{
 
137
        pdl_magic_perlfunc *magp = (pdl_magic_perlfunc *)mag;
 
138
        dSP;
 
139
        PUSHMARK(sp);
 
140
        perl_call_sv(magp->sv, G_DISCARD | G_NOARGS);
 
141
        return NULL;
 
142
}
 
143
 
 
144
static pdl_magic_vtable svmagic_vtable = {
 
145
        svmagic_cast,
 
146
        NULL
 
147
};
 
148
 
 
149
pdl_magic *pdl_add_svmagic(pdl *it,SV *func)
 
150
{
 
151
        AV *av;
 
152
        pdl_magic_perlfunc *ptr = malloc(sizeof(pdl_magic_perlfunc));
 
153
        ptr->what = PDL_MAGIC_MARKCHANGED | PDL_MAGIC_DELAYED;
 
154
        ptr->vtable = &svmagic_vtable;
 
155
        ptr->sv = newSVsv(func);
 
156
        ptr->pdl = it;
 
157
        ptr->next = NULL;
 
158
        pdl__magic_add(it,(pdl_magic *)ptr);
 
159
        if(it->state & PDL_ANYCHANGED)
 
160
                pdl_add_delayed_magic((pdl_magic *)ptr);
 
161
/* In order to have our SV destroyed in time for the interpreter, */
 
162
/* XXX Work this out not to memleak */
 
163
        av = perl_get_av("PDL::disposable_svmagics",TRUE);
 
164
        av_push(av,ptr->sv);
 
165
        return (pdl_magic *)ptr;
 
166
}
 
167
 
 
168
 
 
169
/****************
 
170
 *
 
171
 * ->bind - magic
 
172
 */
 
173
 
 
174
pdl_trans *pdl_find_mutatedtrans(pdl *it)
 
175
{
 
176
        if(!it->magic) return 0;
 
177
        return pdl__call_magic(it,PDL_MAGIC_MUTATEDPARENT);
 
178
}
 
179
 
 
180
static void *fammutmagic_cast(pdl_magic *mag)
 
181
{
 
182
        pdl_magic_fammut *magp = (pdl_magic_fammut *)mag;
 
183
        return magp->ftr;
 
184
}
 
185
 
 
186
struct pdl_magic_vtable familymutmagic_vtable = {
 
187
        fammutmagic_cast,
 
188
        NULL
 
189
};
 
190
 
 
191
pdl_magic *pdl_add_fammutmagic(pdl *it,pdl_trans *ft)
 
192
{
 
193
        pdl_magic_fammut *ptr = malloc(sizeof(pdl_magic_fammut));
 
194
        ptr->what = PDL_MAGIC_MUTATEDPARENT;
 
195
        ptr->vtable = &familymutmagic_vtable;
 
196
        ptr->ftr = ft;
 
197
        ptr->pdl = it;
 
198
        ptr->next = NULL;
 
199
        pdl__magic_add(it,(pdl_magic *)ptr);
 
200
        return (pdl_magic *)ptr;
 
201
}
 
202
 
 
203
#ifdef PDL_PTHREAD
 
204
 
 
205
/**************
 
206
 *
 
207
 * pthreads
 
208
 *
 
209
 */
 
210
 
 
211
#define TVERB 0
 
212
 
 
213
typedef struct ptarg {
 
214
        pdl_magic_pthread *mag;
 
215
        void (*func)(pdl_trans *);
 
216
        pdl_trans *t;
 
217
        int no;
 
218
} ptarg;
 
219
 
 
220
int pdl_pthreads_enabled(void) {return 1;}
 
221
 
 
222
static void *pthread_perform(void *vp) {
 
223
        struct ptarg *p = (ptarg *)vp;
 
224
        if(TVERB) printf("STARTING THREAD %d (%d)\n",p->no, pthread_self());
 
225
        pthread_setspecific(p->mag->key,(void *)&(p->no));
 
226
        (p->func)(p->t);
 
227
        if(TVERB) printf("ENDING THREAD %d (%d)\n",p->no, pthread_self());
 
228
        return NULL;
 
229
}
 
230
 
 
231
int pdl_magic_thread_nthreads(pdl *it,int *nthdim) {
 
232
        pdl_magic_pthread *ptr = (pdl_magic_pthread *)pdl__find_magic(it,
 
233
                                        PDL_MAGIC_THREADING);
 
234
        if(!ptr) return 0;
 
235
        *nthdim = ptr->nthdim;
 
236
        return ptr->nthreads;
 
237
}
 
238
 
 
239
int pdl_magic_get_thread(pdl *it) { /* XXX -> only one thread can handle pdl at once */
 
240
        pdl_magic_pthread *ptr;
 
241
        int *p;
 
242
        ptr = (pdl_magic_pthread *)pdl__find_magic(it,
 
243
                                        PDL_MAGIC_THREADING);
 
244
        if(!ptr) {die("Invalid pdl_magic_get_thread!");}
 
245
        p = (int*)pthread_getspecific(ptr->key);
 
246
        if(!p) {
 
247
                die("Invalid pdl_magic_get_thread specific!!!!");
 
248
        }
 
249
        return *p;
 
250
}
 
251
 
 
252
void pdl_magic_thread_cast(pdl *it,void (*func)(pdl_trans *),pdl_trans *t) {
 
253
        pdl_magic_pthread *ptr; pthread_t *tp; ptarg *tparg;
 
254
        int i;
 
255
        ptr = (pdl_magic_pthread *)pdl__find_magic(it,
 
256
                                        PDL_MAGIC_THREADING);
 
257
        if(!ptr) {die("Invalid pdl_magic_thread_cast!");}
 
258
        tp = malloc(sizeof(pthread_t) * ptr->nthreads);
 
259
        tparg = malloc(sizeof(*tparg) * ptr->nthreads);
 
260
        pthread_key_create(&(ptr->key),NULL);
 
261
        if(TVERB) printf("CREATING THREADS, ME: %d, key: %d\n",pthread_self(),
 
262
                ptr->key);
 
263
        for(i=0; i<ptr->nthreads; i++) {
 
264
                tparg[i].mag = ptr;
 
265
                tparg[i].func = func;
 
266
                tparg[i].t = t;
 
267
                tparg[i].no = i;
 
268
                pthread_create(tp+i, NULL, pthread_perform, tparg+i);
 
269
        }
 
270
        if(TVERB) printf("JOINING THREADS, ME: %d, key: %d\n",pthread_self(),
 
271
                ptr->key);
 
272
        for(i=0; i<ptr->nthreads; i++) {
 
273
                pthread_join(tp[i], NULL);
 
274
        }
 
275
        if(TVERB) printf("FINISHED THREADS, ME: %d, key: %d\n",pthread_self(),
 
276
                ptr->key);
 
277
        pthread_key_delete((ptr->key));
 
278
}
 
279
 
 
280
void pdl_add_threading_magic(pdl *it,int nthdim,int nthreads)
 
281
{
 
282
        pdl_magic_pthread *ptr = malloc(sizeof(pdl_magic_pthread));
 
283
        ptr->what = PDL_MAGIC_THREADING;
 
284
        ptr->vtable = NULL;
 
285
        ptr->next = NULL;
 
286
        ptr->nthdim = nthdim;
 
287
        ptr->nthreads = nthreads;
 
288
        pdl__magic_add(it,(pdl_magic *)ptr);
 
289
}
 
290
 
 
291
#else
 
292
/* Dummy versions */
 
293
void pdl_add_threading_magic(pdl *it,int nthdim,int nthreads) {}
 
294
int pdl_magic_get_thread(pdl *it) {return 0;}
 
295
void pdl_magic_thread_cast(pdl *it,void (*func)(pdl_trans *),pdl_trans *t) {}
 
296
int pdl_magic_thread_nthreads(pdl *it,int *nthdim) {return 0;}
 
297
int pdl_pthreads_enabled() {return 0;}
 
298
#endif
 
299
 
 
300
/***************************
 
301
 *
 
302
 * Delete magic
 
303
 *
 
304
 */
 
305
 
 
306
 
 
307
void pdl_delete_mmapped_data(pdl *p, int param)
 
308
{
 
309
        if(!p) {return;}
 
310
        if(!p->data) {return;}
 
311
#ifdef USE_MMAP
 
312
        munmap(p->data, param);
 
313
#else
 
314
        croak("internal error: trying to delete mmaped data on unsupported platform");
 
315
#endif
 
316
        p->data = 0;
 
317
}
 
318
 
 
319
static void *delete_mmapped_cast(pdl_magic *mag)
 
320
{
 
321
        pdl_magic_deletedata *magp = (pdl_magic_deletedata *)mag;
 
322
        magp->func(magp->pdl, magp->param);
 
323
        return NULL;
 
324
}
 
325
 
 
326
struct pdl_magic_vtable deletedatamagic_vtable = {
 
327
        delete_mmapped_cast,
 
328
        NULL
 
329
};
 
330
 
 
331
void pdl_add_deletedata_magic(pdl *it, void (*func)(pdl *, int param), int param)
 
332
{
 
333
        pdl_magic_deletedata *ptr = malloc(sizeof(pdl_magic_deletedata));
 
334
        ptr->what = PDL_MAGIC_DELETEDATA;
 
335
        ptr->vtable = &deletedatamagic_vtable;
 
336
        ptr->pdl = it;
 
337
        ptr->func = func;
 
338
        ptr->param = param;
 
339
        pdl__magic_add(it, (pdl_magic *)ptr);
 
340
}
 
341