/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- Scm_ParameterTableInit
- Scm_MakeParameterSlot
- Scm_ParameterRef
- Scm_ParameterSet
- Scm__InitParameter
1 /*
2 * parameter.c - parameter support
3 *
4 * Copyright (c) 2000-2003 Shiro Kawai, All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the authors nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id: parameter.c,v 1.6 2004/07/15 23:16:13 shirok Exp $
34 */
35
36 #define LIBGAUCHE_BODY
37 #include "gauche.h"
38 #include "gauche/vm.h"
39
40 /*
41 * Parameters keep thread-local states. When a thread is created,
42 * it inherits the set of parameters from its creator (except the
43 * primordial thread).
44 * Parameters have additional features, such as guard procedure
45 * and observer callbacks. They are implemented in Scheme level
46 * (see lib/gauche/parameter.scm). C level only provides low-level
47 * accessor and modifier methods.
48 *
49 * It is debatable how to implement the inheritance semantics. MzScheme
50 * keeps user-defined parameters in a hash table, and uses
51 * copy-on-write mechanism to delay the copy of the table. It is nice,
52 * but difficult to use in preemptive threads, for it requires lock of
53 * the table every time even in reading parameters. Guile uses the
54 * vector (Guile calls them fluids, but it's semantically equivalent
55 * to parameters), and eagerly copies the vector at the creation of the
56 * thread. Since thread creation in Gauche is already heavy anyway,
57 * I take Guile's approach.
58 */
59
60 #define PARAMETER_INIT_SIZE 64
61 #define PARAMETER_GROW 16
62
63 /* Every time a new parameter is created (in any thread), it is
64 * given an unique ID in the process. It prevents a thread from
65 * dereferencnig a parameter created by an unrelated thread.
66 */
67 static int next_parameter_id = 0;
68 ScmInternalMutex parameter_mutex;
69
70 /* Init table. For primordial thread, base == NULL. For non-primordial
71 * thread, base is the current thread (this must be called from the
72 * creator thread).
73 */
74 void Scm_ParameterTableInit(ScmVMParameterTable *table,
75 ScmVM *base)
76 {
77 int i;
78
79 if (base) {
80 table->vector = SCM_NEW_ARRAY(ScmObj, base->parameters.numAllocated);
81 table->ids = SCM_NEW_ATOMIC2(int*, PARAMETER_INIT_SIZE*sizeof(int));
82 table->numAllocated = base->parameters.numAllocated;
83 table->numParameters = base->parameters.numParameters;
84 for (i=0; i<table->numParameters; i++) {
85 table->vector[i] = base->parameters.vector[i];
86 table->ids[i] = base->parameters.ids[i];
87 }
88 } else {
89 table->vector = SCM_NEW_ARRAY(ScmObj, PARAMETER_INIT_SIZE);
90 table->ids = SCM_NEW_ATOMIC2(int*, PARAMETER_INIT_SIZE*sizeof(int));
91 table->numParameters = 0;
92 table->numAllocated = PARAMETER_INIT_SIZE;
93 }
94 }
95
96 /*
97 * Allocate new parameter slot
98 */
99 int Scm_MakeParameterSlot(ScmVM *vm, int *newid)
100 {
101 ScmVMParameterTable *p = &(vm->parameters);
102 if (p->numParameters == p->numAllocated) {
103 int i, newsiz = p->numAllocated + PARAMETER_GROW;
104 ScmObj *newvec = SCM_NEW_ARRAY(ScmObj, newsiz);
105 int *newids = SCM_NEW_ATOMIC2(int*, newsiz*sizeof(int));
106
107 for (i=0; i<p->numParameters; i++) {
108 newvec[i] = p->vector[i];
109 p->vector[i] = SCM_FALSE; /*GC friendly*/
110 newids[i] = p->ids[i];
111 }
112 p->vector = newvec;
113 p->ids = newids;
114 p->numAllocated += PARAMETER_GROW;
115 }
116 p->vector[p->numParameters] = SCM_UNDEFINED;
117 SCM_INTERNAL_MUTEX_LOCK(parameter_mutex);
118 p->ids[p->numParameters] = *newid = next_parameter_id++;
119 SCM_INTERNAL_MUTEX_UNLOCK(parameter_mutex);
120 return p->numParameters++;
121 }
122
123 /*
124 * Accessor & modifier
125 */
126
127 ScmObj Scm_ParameterRef(ScmVM *vm, int index, int id)
128 {
129 ScmVMParameterTable *p = &(vm->parameters);
130 SCM_ASSERT(index >= 0);
131 if (index >= p->numParameters || p->ids[index] != id) {
132 Scm_Error("the thread %S doesn't have parameter (%d:%d)",
133 vm, index, id);
134 }
135 SCM_ASSERT(p->vector[index] != NULL);
136 return p->vector[index];
137 }
138
139 ScmObj Scm_ParameterSet(ScmVM *vm, int index, int id, ScmObj value)
140 {
141 ScmVMParameterTable *p = &(vm->parameters);
142 SCM_ASSERT(index >= 0);
143 if (index >= p->numParameters || p->ids[index] != id) {
144 Scm_Error("the thread %S doesn't have parameter (%d:%d)",
145 vm, index, id);
146 }
147 p->vector[index] = value;
148 return value;
149 }
150
151 /*
152 * Initialization
153 */
154 void Scm__InitParameter(void)
155 {
156 SCM_INTERNAL_MUTEX_INIT(parameter_mutex);
157 }