comparison datum.c @ 0:76568becd6d6

Rhope Alpha 2a source import
author Mike Pavone <pavone@retrodev.com>
date Tue, 28 Apr 2009 23:06:07 +0000
parents
children 23dd9c766699
comparison
equal deleted inserted replaced
-1:000000000000 0:76568becd6d6
1 #include "structs.h"
2 #include "datum.h"
3 #include "interp.h"
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #ifdef WIN32
8 #include <winsock.h>
9 #else
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <netdb.h>
14 #include <arpa/inet.h>
15 #endif
16
17 #ifdef TEXT_FILE_DEBUG
18 extern FILE * debugfile;
19 #endif
20
21 extern char * debugbuffer;
22
23 datum_storage first_datum_storage;
24 datum_storage * first_free;
25
26 VIS_CRITICAL_SECTION(datum_alloc_lock)
27
28 void init_datum_storage()
29 {
30 short i;
31 first_datum_storage.available = DATUMS_PER_STORAGE;
32 for(i = 0; i < DATUMS_PER_STORAGE/8; ++i)
33 first_datum_storage.inuse[i] = 0;
34 first_datum_storage.next = NULL;
35 //first_datum_storage.num = 0;
36 //first_free = &first_datum_storage;
37 VIS_InitializeCriticalSection(datum_alloc_lock);
38 }
39
40 datum * datum_alloc()
41 {
42 short i, j;
43 datum_storage *last, *current = /*first_free;*/&first_datum_storage;
44 VIS_PROFILE_START(PROF_DATUM_ALLOC);
45 //DEBUGPUTS("Begin datum_alloc()\n");
46 VIS_EnterCriticalSection(datum_alloc_lock);
47 while(current && !(current->available))
48 {
49 last = current;
50 current = current->next;
51 }
52 if(current)
53 {
54 for(i = 0; i < (DATUMS_PER_STORAGE >> 3); ++i)
55 if(current->inuse[i] != 0xFF)
56 break;
57 for(j = 0; j < 8; ++j)
58 if(!CHECK_INUSE(current, i, j))
59 break;
60 //DEBUGPRINTF("inuse[%d] = %X\n", i, current->inuse[i]);
61 i = (i << 3) | j;
62 //DEBUGPRINTF("Allocated datum %X:%d\n", current, i);
63 SET_INUSE(current, i);
64 --(current->available);
65 VIS_LeaveCriticalSection(datum_alloc_lock);
66 //DEBUGPUTS("End datum_alloc()\n");
67 //DEBUGPRINTF("datum_alloc(%X)\n", current->datums + i);
68 VIS_PROFILE_END(PROF_DATUM_ALLOC);
69 return current->datums + i;
70 }
71 else
72 {
73 current = MALLOC(sizeof(datum_storage),"datum storage");
74 //first_free = current;
75 //DEBUGPRINTF("New datum_storage %X\n", current);
76 last->next = current;
77 current->available = DATUMS_PER_STORAGE - 1;
78 current->inuse[0] = 1;
79 //current->num = last->num+1;
80 for(i = 1; i < DATUMS_PER_STORAGE>>3; ++i)
81 current->inuse[i] = 0;
82 current->next = NULL;
83 VIS_LeaveCriticalSection(datum_alloc_lock);
84 //DEBUGPUTS("End datum_alloc()\n");
85 //DEBUGPRINTF("datum_alloc(%X)\n", current->datums);
86 VIS_PROFILE_END(PROF_DATUM_ALLOC);
87 return current->datums;
88 }
89
90 }
91
92 void free_datum(datum * adatum)
93 {
94 datum_storage *last=NULL, *current = &first_datum_storage;
95 // DEBUGPUTS("Begin free_datum()\n");
96 VIS_EnterCriticalSection(datum_alloc_lock);
97 while(current && !(adatum >= (datum *)current && adatum <= (((datum *)current) + DATUMS_PER_STORAGE)))
98 {
99 last = current;
100 current = current->next;
101 }
102 if(current)
103 {
104 //DEBUGPRINTF("Freed datum %X:%d\n", current, adatum-((datum *)current));
105 //DEBUGPRINTF("inuse[%d] = %X\n", (adatum-(current->datums))>>3, current->inuse[adatum-(current->datums)>>3]);
106 //DEBUGPRINTF("&= %X\n", ~(1 << ((adatum-(current->datums)) & 3)));
107 CLEAR_INUSE(current, adatum-(current->datums));
108 //DEBUGPRINTF("inuse[%d] = %X\n", (adatum-(current->datums))>>3, current->inuse[adatum-(current->datums)>>3]);
109 ++(current->available);
110 if(current->available == DATUMS_PER_STORAGE && last && last->available)
111 {
112 last->next = NULL;
113 /*last->next = current->next;
114 if(last->num < first_free->num || first_free == current)
115 first_free = last;*/
116 //DEBUGPRINTF("Freeing datum_storage %X\n", current);
117 VIS_FREE(current, "free datum block");
118 }
119 /*else
120 {
121 if(current->num < first_free->num)
122 first_free = current;
123 }*/
124 }
125 VIS_LeaveCriticalSection(datum_alloc_lock);
126 //DEBUGPUTS("End free_datum()\n");
127 }
128
129
130
131 datum * new_datum_comp(company * comp, unsigned char union_type, int generic_len)
132 {
133 datum * adatum;
134 VIS_PROFILE_START(PROF_NEW_DATUM);
135 //adatum = datum_alloc();
136 adatum = MALLOC(sizeof(datum),"datum");
137 DEBUGPRINTF("Allocated: %X\n", adatum);
138 //DEBUGPRINTF("datum_alloc returned %X.\n", adatum);
139 adatum->company = comp;
140 adatum->union_type = union_type;
141 /*if(type > 0)
142 adatum->methods = get_method_list(type);*/
143 if(union_type == 1)//generic data
144 {
145 //DEBUGPUTS("union_type == 1\n");
146 adatum->c.generic.len = generic_len;
147 if(generic_len > 0)
148 {
149 //DEBUGPRINTF("malloc(%d);\n", generic_len);
150 adatum->c.generic.data = MALLOC(generic_len,"datum generic data");
151 //DEBUGPUTS("after malloc");
152 }
153 else
154 adatum->c.generic.data = NULL;
155 }
156 adatum->ref_count = 1;
157 // DEBUGPUTS("Initializing lock.\n");
158 VIS_InitializeCriticalSection(adatum->lock);
159 //DEBUGPRINTF( "New datum at: %X\n", adatum);
160 VIS_PROFILE_END(PROF_NEW_DATUM);
161 return adatum;
162 }
163
164 datum * new_datum(unsigned short type, unsigned char union_type, int generic_len, program * prog)
165 {
166 return new_datum_comp(prog->companylist + type, union_type, generic_len);
167 }
168
169 datum * copy_datum(datum * adatum, int newsize)
170 {
171 //NOTE: This function makes some assumptions that might not be safe everywhere in the interpretter, needs more thought
172 int ref_count, real_len, new_entry_count;
173 dict_data * dict;
174 datum * output;
175 worker_datum * work;
176 int i;
177 VIS_EnterCriticalSection(adatum->lock);
178 ref_count = adatum->ref_count;
179 VIS_LeaveCriticalSection(adatum->lock);
180 if(adatum->union_type == 1)
181 if(adatum->company->type_id == BUILTIN_TYPE_LIST)
182 real_len = (adatum->c.generic.len-1) * sizeof(datum *) + sizeof(list_data);
183 else
184 {
185 real_len = adatum->c.generic.len;
186 }
187 else
188 real_len = 0;
189 if(ref_count > 1 || newsize > real_len)
190 {
191 if(adatum->company->type_id == BUILTIN_TYPE_FILE)
192 {
193 VIS_EnterCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
194 ((file_data *)adatum->c.generic.data)->shared->ref_count++;
195 VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
196 }
197 if(newsize)
198 output = new_datum_comp(adatum->company, adatum->union_type, newsize);
199 else
200 output = new_datum_comp(adatum->company, adatum->union_type, real_len);
201 switch(adatum->union_type)
202 {
203 case 1:
204 if(adatum->company->type_id == BUILTIN_TYPE_LIST)
205 {
206 ((list_data *)output->c.generic.data)->num_entries = ((list_data *)adatum->c.generic.data)->num_entries;
207 for(i = 0; i < ((list_data *)adatum->c.generic.data)->num_entries; ++i)
208 ((list_data *)output->c.generic.data)->entries[i] = add_ref(((list_data *)adatum->c.generic.data)->entries[i]);
209 }
210 #ifdef GUI_LIB
211 else if(adatum->company->type_id == BUILTIN_TYPE_WINDOW)
212 {
213 ((vis_window *)output->c.generic.data)->title = add_ref(((vis_window *)adatum->c.generic.data)->title);
214 ((vis_window *)output->c.generic.data)->widget_dict = add_ref(((vis_window *)adatum->c.generic.data)->widget_dict);
215 ((vis_window *)output->c.generic.data)->widget_xpos = add_ref(((vis_window *)adatum->c.generic.data)->widget_xpos);
216 ((vis_window *)output->c.generic.data)->widget_ypos = add_ref(((vis_window *)adatum->c.generic.data)->widget_ypos);
217 ((vis_window *)output->c.generic.data)->id_list = add_ref(((vis_window *)adatum->c.generic.data)->id_list);
218 ((vis_window *)output->c.generic.data)->width = ((vis_window *)adatum->c.generic.data)->width;
219 ((vis_window *)output->c.generic.data)->height = ((vis_window *)adatum->c.generic.data)->height;
220 }
221 #ifdef SYLLABLE
222 else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON || adatum->company->type_id == BUILTIN_TYPE_INPUTBOX || adatum->company->type_id == BUILTIN_TYPE_CHECKBOX || adatum->company->type_id == BUILTIN_TYPE_DROPDOWN)
223 #else
224 else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON || adatum->company->type_id == BUILTIN_TYPE_INPUTBOX)
225 #endif
226 {
227 ((vis_widget *)output->c.generic.data)->label = add_ref(((vis_widget *)adatum->c.generic.data)->label);
228 ((vis_widget *)output->c.generic.data)->value = add_ref(((vis_widget *)adatum->c.generic.data)->value);
229 ((vis_widget *)output->c.generic.data)->handler_dict = add_ref(((vis_widget *)adatum->c.generic.data)->handler_dict);
230 ((vis_widget *)output->c.generic.data)->width = ((vis_widget *)adatum->c.generic.data)->width;
231 ((vis_widget *)output->c.generic.data)->height = ((vis_widget *)adatum->c.generic.data)->height;
232 ((vis_widget *)output->c.generic.data)->flags = ((vis_widget *)adatum->c.generic.data)->flags;
233 }
234 #endif
235 else if(real_len >= newsize && newsize)
236 memcpy(output->c.generic.data, adatum->c.generic.data, newsize);
237 else
238 memcpy(output->c.generic.data, adatum->c.generic.data, real_len);
239
240 if(adatum->company->build_size > 0)
241 {
242 for(i = 0; i < adatum->company->num_rooms; ++i)
243 if(adatum->company->room_list[i].get_func_type == ROOM_VIS_REF)
244 {
245 //DEBUGPRINTF("Member add ref (get_func): %X, generic.data: %X\n", (datum*)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func), adatum->c.generic.data);
246 add_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func)));
247 }
248 else if(adatum->company->room_list[i].set_func_type == ROOM_VIS_REF)
249 {
250 //DEBUGPRINTF("Member add ref (set_func): %X, generic.data: %X\n", (datum*)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func), adatum->c.generic.data);
251 add_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func)));
252 }
253 }
254 else if(adatum->company->type_id == BUILTIN_TYPE_DICT)
255 {
256 dict = output->c.generic.data;
257 for(i = 0; i < dict->num_nodes; ++i)
258 add_ref(dict->nodes[i].payload);
259 }
260 else if(adatum->company->type_id == BUILTIN_TYPE_WORKER)
261 {
262 work = output->c.generic.data;
263 add_program_ref(work->def->program);
264 for(i = 0; i < work->def->num_inputs; ++i)
265 add_ref(work->params[i]);
266 }
267
268 if(adatum->c.generic.len != real_len)
269 output->c.generic.len = adatum->c.generic.len;
270 break;
271 case 2:
272 output->c.integers.num_a = adatum->c.integers.num_a;
273 output->c.integers.num_b = adatum->c.integers.num_b;
274 break;
275 case 3:
276 output->c.real = adatum->c.real;
277 break;
278 default:
279 //oops;
280 break;
281 }
282 release_ref(adatum);
283 }
284 else if(newsize && real_len == adatum->c.generic.len)
285 {
286 adatum->c.generic.len = newsize;
287 output = adatum;
288 }
289 else
290 output = adatum;
291 return output;
292 }
293
294 datum * add_ref(datum * adatum)
295 {
296 int tmp;
297 VIS_PROFILE_START(PROF_ADDREF);
298 if(!adatum)
299 {
300 //DEBUGPUTS("add_ref on NULL datum\n");
301 return NULL;
302 }
303 DEBUGPRINTF("add_ref: %X\n",adatum);
304 /*tmp = (int)(&(adatum->ref_count));
305 __asm
306 {
307 mov ebx, tmp
308 lock inc dword ptr [ebx]
309 }*/
310
311 VIS_EnterCriticalSection(adatum->lock);
312 ++(adatum->ref_count);
313 VIS_LeaveCriticalSection(adatum->lock);
314 VIS_PROFILE_END(PROF_ADDREF);
315 return adatum;
316 }
317
318 void release_ref(datum * adatum)
319 {
320 int i,tmp;
321 dict_data * dict;
322 worker_datum * worker;
323 VIS_PROFILE_START(PROF_RELEASE);
324 DEBUGPRINTF( "relase_ref: %X\n",adatum);
325 if(!adatum)
326 return;
327
328 /*tmp = (int)(&(adatum->ref_count));
329 __asm
330 {
331 mov ebx, tmp
332 lock dec dword ptr [ebx]
333 }*/
334 //DEBUGPUTS("entering lock");
335 VIS_EnterCriticalSection(adatum->lock);
336 //DEBUGPUTS("got critical section\n");
337 --(adatum->ref_count);
338 if(adatum->ref_count == 0)
339 {
340 //DEBUGPRINTF("datum_free(%X)\n", adatum);
341
342 VIS_LeaveCriticalSection(adatum->lock);
343 //DEBUGPUTS("left lock");
344 VIS_DeleteCriticalSection(adatum->lock);
345 if(adatum->union_type == 1)
346 {
347 //DEBUGPRINTF( "Freeing adatum->c.generic.data(%X)\n",(int)adatum->c.generic.data);
348 if(adatum->company->build_size > 0)
349 {
350 for(i = 0; i < adatum->company->num_rooms; ++i)
351 if(adatum->company->room_list[i].get_func_type == ROOM_VIS_REF)
352 {
353 //DEBUGPRINTF("Member release ref (get_func): %X, generic.data: %X\n", (datum*)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func), adatum->c.generic.data);
354 release_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func)));
355 }
356 else if(adatum->company->room_list[i].set_func_type == ROOM_VIS_REF)
357 {
358 //DEBUGPRINTF("Member release ref (set_func): %X, generic.data: %X\n", (datum*)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func), adatum->c.generic.data);
359 release_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func)));
360 }
361 }
362 else if(adatum->company->type_id == BUILTIN_TYPE_LIST)
363 for(i = 0; i < ((list_data *)adatum->c.generic.data)->num_entries; ++i)
364 release_ref(((list_data *)adatum->c.generic.data)->entries[i]);
365 else if(adatum->company->type_id == BUILTIN_TYPE_FILE)
366 {
367 VIS_EnterCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
368 --(((file_data *)adatum->c.generic.data)->shared->ref_count);
369 if(((file_data *)adatum->c.generic.data)->shared->ref_count == 0)
370 {
371 VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
372 VIS_DeleteCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
373 #ifndef SEGA
374 if(((file_data *)adatum->c.generic.data)->shared->status == FILE_READ || ((file_data *)adatum->c.generic.data)->shared->status == FILE_WRITE)
375 fclose(((file_data *)adatum->c.generic.data)->shared->file);
376 #endif
377 VIS_FREE(((file_data *)adatum->c.generic.data)->shared, "Shared file struct");
378 }
379 else
380 {
381 VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock);
382 }
383 }
384 else if(adatum->company->type_id == BUILTIN_TYPE_DICT)
385 {
386 dict = adatum->c.generic.data;
387 for(i = 0; i < dict->num_nodes; ++i)
388 release_ref(dict->nodes[i].payload);
389 }
390 else if(adatum->company->type_id == BUILTIN_TYPE_WORKER)
391 {
392 worker = adatum->c.generic.data;
393 for(i = 0; i < worker->def->num_inputs; ++i)
394 if(worker->params[i])
395 {
396 DEBUGPRINTF("Releasing worker param %d\n", i);
397 release_ref(worker->params[i]);
398 }
399 release_program_ref(worker->def->program);
400 }
401 #ifdef SYLLABLE
402 else if(adatum->company->type_id == BUILTIN_TYPE_WINDOW)
403 {
404 release_ref(((vis_window *)adatum->c.generic.data)->title);
405 release_ref(((vis_window *)adatum->c.generic.data)->widget_dict);
406 release_ref(((vis_window *)adatum->c.generic.data)->widget_xpos);
407 release_ref(((vis_window *)adatum->c.generic.data)->widget_ypos);
408 release_ref(((vis_window *)adatum->c.generic.data)->id_list);
409 }
410 else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON)
411 {
412 release_ref(((vis_widget *)adatum->c.generic.data)->label);
413 release_ref(((vis_widget *)adatum->c.generic.data)->handler_dict);
414 }
415 #endif
416 VIS_FREE(adatum->c.generic.data, "datum->c.generic.data");
417 } else if(adatum->company->type_id == BUILTIN_TYPE_NETCLIENT)
418 #ifdef WIN32
419 closesocket(adatum->c.integers.num_a);
420 #else
421 close(adatum->c.integers.num_a);
422 #endif
423 else if(adatum->company->type_id == BUILTIN_TYPE_PROGRAM)
424 release_program_ref(adatum->c.generic.data);
425 DEBUGPRINTF("Freeing: %X\n",adatum);
426 //free_datum(adatum);
427 free(adatum);
428 }
429 else
430 {
431 VIS_LeaveCriticalSection(adatum->lock);
432 //DEBUGPUTS("left lock");
433 }
434 VIS_PROFILE_END(PROF_RELEASE);
435 //DEBUGPUTS("exit release_ref\n");
436
437 }
438
439 void datum_set_yesno(datum * adatum, int val)
440 {
441 adatum->c.integers.num_a = val;
442 }
443
444
445
446
447
448