2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / jni / classpath / native_state.c
blob746686edd9748112438ea916662c3d6592828ee9
1 /* Magical NSA API -- Associate a C ptr with an instance of an object
2 Copyright (C) 1998, 2002 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 #include <stdlib.h>
39 #include <jni.h>
40 #include "native_state.h"
42 #define DEFAULT_TABLE_SIZE 97
44 struct state_table *
45 init_state_table_with_size (JNIEnv *env, jclass clazz, jint size)
47 struct state_table *table;
48 jfieldID hash;
49 jclass clazz_g;
51 hash = (*env)->GetFieldID (env, clazz, "native_state", "I");
52 if (hash == NULL)
53 return NULL;
55 clazz_g = (*env)->NewGlobalRef (env, clazz);
56 if (clazz_g == NULL)
57 return NULL;
59 table = (struct state_table *) malloc (sizeof (struct state_table));
60 table->size = size;
61 table->head = (struct state_node **) calloc (sizeof (struct state_node *),
62 table->size);
63 table->hash = hash;
64 table->clazz = clazz_g;
66 return table;
69 struct state_table *
70 init_state_table (JNIEnv *env, jclass clazz)
72 return init_state_table_with_size (env, clazz, DEFAULT_TABLE_SIZE);
75 static void *
76 remove_node (struct state_node **head, jint obj_id)
78 struct state_node *back_ptr = NULL;
79 struct state_node *node = *head;
81 while (node != NULL)
83 if (node->key == obj_id)
85 void *return_value;
86 if (back_ptr == NULL)
87 *head = node->next;
88 else
89 back_ptr->next = node->next;
90 return_value = node->c_state;
91 free (node);
92 return return_value;
94 back_ptr = node;
95 node = node->next;
98 return NULL;
101 static void *
102 get_node (struct state_node **head, jint obj_id)
104 struct state_node *back_ptr = NULL;
105 struct state_node *node = *head;
107 while (node != NULL)
109 if (node->key == obj_id)
111 /* Move the node we found to the front of the list. */
112 if (back_ptr != NULL)
114 back_ptr->next = node->next;
115 node->next = *head;
116 *head = node;
119 /* Return the match. */
120 return node->c_state;
123 back_ptr = node;
124 node = node->next;
127 return NULL;
130 static void
131 add_node (struct state_node **head, jint obj_id, void *state)
133 struct state_node *node = *head;
134 struct state_node *back_ptr = NULL;
136 struct state_node *new_node;
138 if (node != NULL)
140 while (node->next != NULL && obj_id != node->key)
142 back_ptr = node;
143 node = node->next;
146 if (node->key == obj_id)
148 /* If we're updating a node, move it to the front of the
149 list. */
150 if (back_ptr != NULL)
152 back_ptr->next = node->next;
153 node->next = *head;
155 node->c_state = state;
156 return;
160 new_node = (struct state_node *) malloc (sizeof (struct state_node));
161 new_node->key = obj_id;
162 new_node->c_state = state;
163 new_node->next = *head;
164 *head = new_node;
167 void
168 set_state_oid (JNIEnv *env, jobject lock, struct state_table *table,
169 jint obj_id, void *state)
171 jint hash;
173 hash = obj_id % table->size;
175 (*env)->MonitorEnter (env, lock);
176 add_node (&table->head[hash], obj_id, state);
177 (*env)->MonitorExit (env, lock);
180 void *
181 get_state_oid (JNIEnv *env, jobject lock, struct state_table *table,
182 jint obj_id)
184 jint hash;
185 void *return_value;
187 hash = obj_id % table->size;
189 (*env)->MonitorEnter (env, lock);
190 return_value = get_node (&table->head[hash], obj_id);
191 (*env)->MonitorExit (env, lock);
193 return return_value;
196 void *
197 remove_state_oid (JNIEnv *env, jobject lock, struct state_table *table,
198 jint obj_id)
200 jint hash;
201 void *return_value;
203 hash = obj_id % table->size;
205 (*env)->MonitorEnter (env, lock);
206 return_value = remove_node (&table->head[hash], obj_id);
207 (*env)->MonitorExit (env, lock);
209 return return_value;
213 set_state (JNIEnv *env, jobject obj, struct state_table *table, void *state)
215 jint obj_id;
216 obj_id = (*env)->GetIntField (env, obj, table->hash);
218 if ((*env)->ExceptionOccurred (env) != NULL)
219 return -1;
221 set_state_oid (env, table->clazz, table, obj_id, state);
222 return 0;
225 void *
226 get_state (JNIEnv *env, jobject obj, struct state_table *table)
228 jint obj_id;
229 obj_id = (*env)->GetIntField (env, obj, table->hash);
231 if ((*env)->ExceptionOccurred (env) != NULL)
232 return NULL;
234 return get_state_oid (env, table->clazz, table, obj_id);
237 void *
238 remove_state_slot (JNIEnv *env, jobject obj, struct state_table *table)
240 jint obj_id;
241 obj_id = (*env)->GetIntField (env, obj, table->hash);
243 if ((*env)->ExceptionOccurred (env) != NULL)
244 return NULL;
246 return remove_state_oid (env, table->clazz, table, obj_id);