Mercurial > repos > rhope
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datum.c Tue Apr 28 23:06:07 2009 +0000 @@ -0,0 +1,448 @@ +#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 SYLLABLE + 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; +} + + + + + +