Mercurial > repos > rhope
view datum.c @ 124:8aedae4f4ddd
Add support for Int32 as Dictionary key
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 28 Oct 2010 21:05:50 -0400 |
parents | 23dd9c766699 |
children |
line wrap: on
line source
#include "structs.h" #include "datum.h" #include "interp.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32 #include <winsock.h> #else #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h> #endif #ifdef TEXT_FILE_DEBUG extern FILE * debugfile; #endif extern char * debugbuffer; datum_storage first_datum_storage; datum_storage * first_free; VIS_CRITICAL_SECTION(datum_alloc_lock) void init_datum_storage() { short i; first_datum_storage.available = DATUMS_PER_STORAGE; for(i = 0; i < DATUMS_PER_STORAGE/8; ++i) first_datum_storage.inuse[i] = 0; first_datum_storage.next = NULL; //first_datum_storage.num = 0; //first_free = &first_datum_storage; VIS_InitializeCriticalSection(datum_alloc_lock); } datum * datum_alloc() { short i, j; datum_storage *last, *current = /*first_free;*/&first_datum_storage; VIS_PROFILE_START(PROF_DATUM_ALLOC); //DEBUGPUTS("Begin datum_alloc()\n"); VIS_EnterCriticalSection(datum_alloc_lock); while(current && !(current->available)) { last = current; current = current->next; } if(current) { for(i = 0; i < (DATUMS_PER_STORAGE >> 3); ++i) if(current->inuse[i] != 0xFF) break; for(j = 0; j < 8; ++j) if(!CHECK_INUSE(current, i, j)) break; //DEBUGPRINTF("inuse[%d] = %X\n", i, current->inuse[i]); i = (i << 3) | j; //DEBUGPRINTF("Allocated datum %X:%d\n", current, i); SET_INUSE(current, i); --(current->available); VIS_LeaveCriticalSection(datum_alloc_lock); //DEBUGPUTS("End datum_alloc()\n"); //DEBUGPRINTF("datum_alloc(%X)\n", current->datums + i); VIS_PROFILE_END(PROF_DATUM_ALLOC); return current->datums + i; } else { current = MALLOC(sizeof(datum_storage),"datum storage"); //first_free = current; //DEBUGPRINTF("New datum_storage %X\n", current); last->next = current; current->available = DATUMS_PER_STORAGE - 1; current->inuse[0] = 1; //current->num = last->num+1; for(i = 1; i < DATUMS_PER_STORAGE>>3; ++i) current->inuse[i] = 0; current->next = NULL; VIS_LeaveCriticalSection(datum_alloc_lock); //DEBUGPUTS("End datum_alloc()\n"); //DEBUGPRINTF("datum_alloc(%X)\n", current->datums); VIS_PROFILE_END(PROF_DATUM_ALLOC); return current->datums; } } void free_datum(datum * adatum) { datum_storage *last=NULL, *current = &first_datum_storage; // DEBUGPUTS("Begin free_datum()\n"); VIS_EnterCriticalSection(datum_alloc_lock); while(current && !(adatum >= (datum *)current && adatum <= (((datum *)current) + DATUMS_PER_STORAGE))) { last = current; current = current->next; } if(current) { //DEBUGPRINTF("Freed datum %X:%d\n", current, adatum-((datum *)current)); //DEBUGPRINTF("inuse[%d] = %X\n", (adatum-(current->datums))>>3, current->inuse[adatum-(current->datums)>>3]); //DEBUGPRINTF("&= %X\n", ~(1 << ((adatum-(current->datums)) & 3))); CLEAR_INUSE(current, adatum-(current->datums)); //DEBUGPRINTF("inuse[%d] = %X\n", (adatum-(current->datums))>>3, current->inuse[adatum-(current->datums)>>3]); ++(current->available); if(current->available == DATUMS_PER_STORAGE && last && last->available) { last->next = NULL; /*last->next = current->next; if(last->num < first_free->num || first_free == current) first_free = last;*/ //DEBUGPRINTF("Freeing datum_storage %X\n", current); VIS_FREE(current, "free datum block"); } /*else { if(current->num < first_free->num) first_free = current; }*/ } VIS_LeaveCriticalSection(datum_alloc_lock); //DEBUGPUTS("End free_datum()\n"); } datum * new_datum_comp(company * comp, unsigned char union_type, int generic_len) { datum * adatum; VIS_PROFILE_START(PROF_NEW_DATUM); //adatum = datum_alloc(); adatum = MALLOC(sizeof(datum),"datum"); DEBUGPRINTF("Allocated: %X\n", adatum); //DEBUGPRINTF("datum_alloc returned %X.\n", adatum); adatum->company = comp; adatum->union_type = union_type; /*if(type > 0) adatum->methods = get_method_list(type);*/ if(union_type == 1)//generic data { //DEBUGPUTS("union_type == 1\n"); adatum->c.generic.len = generic_len; if(generic_len > 0) { //DEBUGPRINTF("malloc(%d);\n", generic_len); adatum->c.generic.data = MALLOC(generic_len,"datum generic data"); //DEBUGPUTS("after malloc"); } else adatum->c.generic.data = NULL; } adatum->ref_count = 1; // DEBUGPUTS("Initializing lock.\n"); VIS_InitializeCriticalSection(adatum->lock); //DEBUGPRINTF( "New datum at: %X\n", adatum); VIS_PROFILE_END(PROF_NEW_DATUM); return adatum; } datum * new_datum(unsigned short type, unsigned char union_type, int generic_len, program * prog) { return new_datum_comp(prog->companylist + type, union_type, generic_len); } datum * copy_datum(datum * adatum, int newsize) { //NOTE: This function makes some assumptions that might not be safe everywhere in the interpretter, needs more thought int ref_count, real_len, new_entry_count; dict_data * dict; datum * output; worker_datum * work; int i; VIS_EnterCriticalSection(adatum->lock); ref_count = adatum->ref_count; VIS_LeaveCriticalSection(adatum->lock); if(adatum->union_type == 1) if(adatum->company->type_id == BUILTIN_TYPE_LIST) real_len = (adatum->c.generic.len-1) * sizeof(datum *) + sizeof(list_data); else { real_len = adatum->c.generic.len; } else real_len = 0; if(ref_count > 1 || newsize > real_len) { if(adatum->company->type_id == BUILTIN_TYPE_FILE) { VIS_EnterCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); ((file_data *)adatum->c.generic.data)->shared->ref_count++; VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); } if(newsize) output = new_datum_comp(adatum->company, adatum->union_type, newsize); else output = new_datum_comp(adatum->company, adatum->union_type, real_len); switch(adatum->union_type) { case 1: if(adatum->company->type_id == BUILTIN_TYPE_LIST) { ((list_data *)output->c.generic.data)->num_entries = ((list_data *)adatum->c.generic.data)->num_entries; for(i = 0; i < ((list_data *)adatum->c.generic.data)->num_entries; ++i) ((list_data *)output->c.generic.data)->entries[i] = add_ref(((list_data *)adatum->c.generic.data)->entries[i]); } #ifdef GUI_LIB else if(adatum->company->type_id == BUILTIN_TYPE_WINDOW) { ((vis_window *)output->c.generic.data)->title = add_ref(((vis_window *)adatum->c.generic.data)->title); ((vis_window *)output->c.generic.data)->widget_dict = add_ref(((vis_window *)adatum->c.generic.data)->widget_dict); ((vis_window *)output->c.generic.data)->widget_xpos = add_ref(((vis_window *)adatum->c.generic.data)->widget_xpos); ((vis_window *)output->c.generic.data)->widget_ypos = add_ref(((vis_window *)adatum->c.generic.data)->widget_ypos); ((vis_window *)output->c.generic.data)->id_list = add_ref(((vis_window *)adatum->c.generic.data)->id_list); ((vis_window *)output->c.generic.data)->width = ((vis_window *)adatum->c.generic.data)->width; ((vis_window *)output->c.generic.data)->height = ((vis_window *)adatum->c.generic.data)->height; } #ifdef SYLLABLE 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) #else else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON || adatum->company->type_id == BUILTIN_TYPE_INPUTBOX) #endif { ((vis_widget *)output->c.generic.data)->label = add_ref(((vis_widget *)adatum->c.generic.data)->label); ((vis_widget *)output->c.generic.data)->value = add_ref(((vis_widget *)adatum->c.generic.data)->value); ((vis_widget *)output->c.generic.data)->handler_dict = add_ref(((vis_widget *)adatum->c.generic.data)->handler_dict); ((vis_widget *)output->c.generic.data)->width = ((vis_widget *)adatum->c.generic.data)->width; ((vis_widget *)output->c.generic.data)->height = ((vis_widget *)adatum->c.generic.data)->height; ((vis_widget *)output->c.generic.data)->flags = ((vis_widget *)adatum->c.generic.data)->flags; } #endif else if(real_len >= newsize && newsize) memcpy(output->c.generic.data, adatum->c.generic.data, newsize); else memcpy(output->c.generic.data, adatum->c.generic.data, real_len); if(adatum->company->build_size > 0) { for(i = 0; i < adatum->company->num_rooms; ++i) if(adatum->company->room_list[i].get_func_type == ROOM_VIS_REF) { //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); add_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func))); } else if(adatum->company->room_list[i].set_func_type == ROOM_VIS_REF) { //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); add_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func))); } } else if(adatum->company->type_id == BUILTIN_TYPE_DICT) { dict = output->c.generic.data; for(i = 0; i < dict->num_nodes; ++i) add_ref(dict->nodes[i].payload); } else if(adatum->company->type_id == BUILTIN_TYPE_WORKER) { work = output->c.generic.data; add_program_ref(work->def->program); for(i = 0; i < work->def->num_inputs; ++i) add_ref(work->params[i]); } if(adatum->c.generic.len != real_len) output->c.generic.len = adatum->c.generic.len; break; case 2: output->c.integers.num_a = adatum->c.integers.num_a; output->c.integers.num_b = adatum->c.integers.num_b; break; case 3: output->c.real = adatum->c.real; break; default: //oops; break; } release_ref(adatum); } else if(newsize && real_len == adatum->c.generic.len) { adatum->c.generic.len = newsize; output = adatum; } else output = adatum; return output; } datum * add_ref(datum * adatum) { int tmp; VIS_PROFILE_START(PROF_ADDREF); if(!adatum) { //DEBUGPUTS("add_ref on NULL datum\n"); return NULL; } DEBUGPRINTF("add_ref: %X\n",adatum); /*tmp = (int)(&(adatum->ref_count)); __asm { mov ebx, tmp lock inc dword ptr [ebx] }*/ VIS_EnterCriticalSection(adatum->lock); ++(adatum->ref_count); VIS_LeaveCriticalSection(adatum->lock); VIS_PROFILE_END(PROF_ADDREF); return adatum; } void release_ref(datum * adatum) { int i,tmp; dict_data * dict; worker_datum * worker; VIS_PROFILE_START(PROF_RELEASE); DEBUGPRINTF( "relase_ref: %X\n",adatum); if(!adatum) return; /*tmp = (int)(&(adatum->ref_count)); __asm { mov ebx, tmp lock dec dword ptr [ebx] }*/ //DEBUGPUTS("entering lock"); VIS_EnterCriticalSection(adatum->lock); //DEBUGPUTS("got critical section\n"); --(adatum->ref_count); if(adatum->ref_count == 0) { //DEBUGPRINTF("datum_free(%X)\n", adatum); VIS_LeaveCriticalSection(adatum->lock); //DEBUGPUTS("left lock"); VIS_DeleteCriticalSection(adatum->lock); if(adatum->union_type == 1) { //DEBUGPRINTF( "Freeing adatum->c.generic.data(%X)\n",(int)adatum->c.generic.data); if(adatum->company->build_size > 0) { for(i = 0; i < adatum->company->num_rooms; ++i) if(adatum->company->room_list[i].get_func_type == ROOM_VIS_REF) { //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); release_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].get_func))); } else if(adatum->company->room_list[i].set_func_type == ROOM_VIS_REF) { //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); release_ref(*((datum**)(((char *)adatum->c.generic.data) + (int)adatum->company->room_list[i].set_func))); } } else if(adatum->company->type_id == BUILTIN_TYPE_LIST) for(i = 0; i < ((list_data *)adatum->c.generic.data)->num_entries; ++i) release_ref(((list_data *)adatum->c.generic.data)->entries[i]); else if(adatum->company->type_id == BUILTIN_TYPE_FILE) { VIS_EnterCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); --(((file_data *)adatum->c.generic.data)->shared->ref_count); if(((file_data *)adatum->c.generic.data)->shared->ref_count == 0) { VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); VIS_DeleteCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); #ifndef SEGA if(((file_data *)adatum->c.generic.data)->shared->status == FILE_READ || ((file_data *)adatum->c.generic.data)->shared->status == FILE_WRITE) fclose(((file_data *)adatum->c.generic.data)->shared->file); #endif VIS_FREE(((file_data *)adatum->c.generic.data)->shared, "Shared file struct"); } else { VIS_LeaveCriticalSection(((file_data *)adatum->c.generic.data)->shared->lock); } } else if(adatum->company->type_id == BUILTIN_TYPE_DICT) { dict = adatum->c.generic.data; for(i = 0; i < dict->num_nodes; ++i) release_ref(dict->nodes[i].payload); } else if(adatum->company->type_id == BUILTIN_TYPE_WORKER) { worker = adatum->c.generic.data; for(i = 0; i < worker->def->num_inputs; ++i) if(worker->params[i]) { DEBUGPRINTF("Releasing worker param %d\n", i); release_ref(worker->params[i]); } release_program_ref(worker->def->program); } #ifdef GUI_LIB else if(adatum->company->type_id == BUILTIN_TYPE_WINDOW) { release_ref(((vis_window *)adatum->c.generic.data)->title); release_ref(((vis_window *)adatum->c.generic.data)->widget_dict); release_ref(((vis_window *)adatum->c.generic.data)->widget_xpos); release_ref(((vis_window *)adatum->c.generic.data)->widget_ypos); release_ref(((vis_window *)adatum->c.generic.data)->id_list); } else if(adatum->company->type_id == BUILTIN_TYPE_BUTTON) { release_ref(((vis_widget *)adatum->c.generic.data)->label); release_ref(((vis_widget *)adatum->c.generic.data)->handler_dict); } #endif VIS_FREE(adatum->c.generic.data, "datum->c.generic.data"); } else if(adatum->company->type_id == BUILTIN_TYPE_NETCLIENT) #ifdef WIN32 closesocket(adatum->c.integers.num_a); #else close(adatum->c.integers.num_a); #endif else if(adatum->company->type_id == BUILTIN_TYPE_PROGRAM) release_program_ref(adatum->c.generic.data); DEBUGPRINTF("Freeing: %X\n",adatum); //free_datum(adatum); free(adatum); } else { VIS_LeaveCriticalSection(adatum->lock); //DEBUGPUTS("left lock"); } VIS_PROFILE_END(PROF_RELEASE); //DEBUGPUTS("exit release_ref\n"); } void datum_set_yesno(datum * adatum, int val) { adatum->c.integers.num_a = val; }