Mercurial > repos > rhope
view worker.c @ 121:1af91ceaaf49
Fixed memory leak when an output is only attached to a single null input
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 28 Oct 2010 21:04:12 -0400 |
parents | 914ad38f9b59 |
children |
line wrap: on
line source
#include "structs.h" #include "interp.h" #include "datum.h" #include "parser.h" #include "saveload.h" #include <stdlib.h> #include <string.h> int vis_worker_from_string(datum ** inputlist, queue_entry * worker_entry) { int i; worker_datum * work; datum * output = new_datum(BUILTIN_TYPE_WORKER, 1, sizeof(worker_datum), worker_entry->instance->def->program); work = output->c.generic.data; find_worker(inputlist[0]->c.generic.data, NULL, NULL, worker_entry->instance->def->program, &work->def); if(work->def) add_program_ref(work->def->program); for(i = 0; i < 32; ++i) work->params[i] = NULL; release_ref(inputlist[0]); inputlist[0] = output; return 0; } BOOL list_to_array(datum * list_dat, datum ** out_params, int num) { int i; datum * params[2]; list_data * list = list_dat->c.generic.data; if(num > list->num_entries) { return FALSE; } for(i = 0; i < num; ++i) out_params[i] = add_ref(list->entries[i]); release_ref(list_dat); return TRUE; } datum * array_to_list(datum ** in_params, int num, program * prog) { int i; datum * params[2]; params[0] = create_list(prog); for(i = 0; i < num; ++i) { params[1] = in_params[i]; vis_list_append(params, NULL); } return params[0]; } int worker_populate_inputs(datum * inputWorker, datum * ioList, datum ** inputlist) { int i,j=0; worker_datum * work = inputWorker->c.generic.data; list_data * list = ioList->c.generic.data; for(i = 0; i < work->def->num_inputs; ++i) if(work->params[i]) { DEBUGPRINTF("Setting input %d to %X from worker object\n", i, work->params[i]); inputlist[i] = add_ref(work->params[i]); } else { if(j < list->num_entries) { DEBUGPRINTF("Setting input %d to %X from input %d\n", i, list->entries[j], j); inputlist[i] = add_ref(list->entries[j]); ++j; } else { ERRORPRINTF("Error: List passed to Do@Worker doesn't have enough entries for worker %s\n", work->def->name); return -1; } } return 0; } int vis_worker_do(datum ** inputlist, queue_entry * worker_entry) { //int i,j; worker_datum * work; //worker_def * def; //list_data * list; datum * inputWorker = inputlist[0]; datum * ioList = inputlist[1]; int returnval; //release_ref(inputlist[0]); work = inputlist[0]->c.generic.data; //list_to_array(inputlist[1], inputlist, work->def->num_inputs); /*list = inputlist[1]->c.generic.data; j = 0; DEBUGPRINTF("vis_worker_do: def_name: %s, num_inputs = %d, list length = %d\n", work->def->name, work->def->num_inputs, list->num_entries); for(i = 0; i < work->def->num_inputs; ++i) if(work->params[i]) { DEBUGPRINTF("Setting input %d to %X from worker object\n", i, work->params[i]); inputlist[i] = add_ref(work->params[i]); } else { DEBUGPRINTF("Setting input %d to %X from input %d, company name: %s\n", i, list->entries[j], j, list->entries[j]->company->name); inputlist[i] = add_ref(list->entries[j]); ++j; }*/ returnval = worker_populate_inputs(inputWorker, ioList, inputlist); release_ref(ioList); if(returnval) { print_stack_trace(worker_entry->instance); return returnval; } if(work->def->program != worker_entry->instance->def->program) { prep_program(work->def->program ); } returnval = execute_def(work->def, *worker_entry, inputlist, pack_list_sub_callback); if(returnval == 0) { inputlist[0] = array_to_list(inputlist, work->def->num_outputs, worker_entry->instance->def->program); /*vis_list_new(params, NULL); DEBUGPRINTF("params[0] after vis_list_new: %X\n", params[0]); for(i = 0; i < work->def->num_outputs; ++i) { params[1] = inputlist[i]; vis_list_append(params, NULL); DEBUGPRINTF("params[0] after vis_list_append: %X\n", params[0]); } inputlist[0] = params[0];*/ } release_ref(inputWorker); return returnval; } int vis_worker_setinput(datum ** inputlist, queue_entry * worker_entry) { worker_datum * work; inputlist[0] = copy_datum(inputlist[0], 0); work = inputlist[0]->c.generic.data; if(inputlist[1]->c.integers.num_a < 32) work->params[inputlist[1]->c.integers.num_a] = inputlist[2]; else { puts("Error: Visuality currently only supports 32 inputs\n"); execute_active = FALSE; return -1; } release_ref(inputlist[1]); inputlist[1] = inputlist[2] = NULL; return 0; } int vis_worker_add_worker_call(datum ** inputlist, queue_entry * worker_entry) { worker_datum * add_work; worker_datum * work = inputlist[0]->c.generic.data; int index; add_work = inputlist[1]->c.generic.data; /*index = add_work->def - work->def->program->deflist; DEBUGPRINTF("work->def: %X, deflist: %X\n", work->def, worker_entry->instance->def->program->deflist); DEBUGPRINTF("work->def->name: %X\n", work->def->name);*/ index = add_worker_to_def(work->def, add_work->def, 1.0, 1.0); release_ref(inputlist[1]); inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = index; return 0; } int vis_worker_add_wire(datum ** inputlist, queue_entry * worker_entry) { worker_datum * work = inputlist[0]->c.generic.data; add_wire(work->def, inputlist[1]->c.integers.num_a, inputlist[2]->c.integers.num_a, inputlist[3]->c.integers.num_a, inputlist[4]->c.integers.num_a); release_ref(inputlist[1]); release_ref(inputlist[2]); release_ref(inputlist[3]); release_ref(inputlist[4]); return 0; } void list_change_program(list_data * list, program * new_prog) { int i; for(i = 0; i < list->num_entries; ++i) { if(list->entries[i] && list->entries[i]->company->type_id < USER_DEFINED_TYPES) { list->entries[i] = copy_datum(list->entries[i], 0); list->entries[i]->company = new_prog->companylist + list->entries[i]->company->type_id; if(list->entries[i]->company->type_id == BUILTIN_TYPE_LIST) list_change_program(list->entries[i]->c.generic.data, new_prog); } } } int vis_worker_add_constant(datum ** inputlist, queue_entry * worker_entry) { datum * constant = inputlist[1]; worker_datum * work = inputlist[0]->c.generic.data; int index = add_constant(work->def, "code generated", 1.0, 1.0); if(worker_entry->instance->def->program != work->def->program && constant->company->type_id < USER_DEFINED_TYPES) { constant = copy_datum(constant, 0); constant->company = work->def->program->companylist + constant->company->type_id; if(constant->company->type_id == BUILTIN_TYPE_LIST) { list_change_program(constant->c.generic.data, work->def->program); } } work->def->implement_func->workerlist[index].value_index = constant; inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = index; return 0; } int vis_worker_add_input(datum ** inputlist, queue_entry * worker_entry) { worker_datum * work = inputlist[0]->c.generic.data; int index = add_input_num(work->def, inputlist[1]->c.generic.data, inputlist[2]->c.integers.num_a, 1.0, 1.0); release_ref(inputlist[1]); release_ref(inputlist[2]); inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = index; return 0; } int vis_worker_add_output(datum ** inputlist, queue_entry * worker_entry) { worker_datum * work = inputlist[0]->c.generic.data; int index = add_output_num(work->def, inputlist[1]->c.generic.data, inputlist[2]->c.integers.num_a, 1.0, 1.0); release_ref(inputlist[1]); release_ref(inputlist[2]); inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = index; return 0; } int vis_worker_add_objectget(datum ** inputlist, queue_entry * worker_entry) { worker_datum * work = inputlist[0]->c.generic.data; int index = add_get_comp_room(work->def, inputlist[1]->c.generic.data, 1.0,1.0); release_ref(inputlist[1]); inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = index; return 0; } int vis_worker_add_objectset(datum ** inputlist, queue_entry * worker_entry) { worker_datum * work = inputlist[0]->c.generic.data; int index = add_set_comp_room(work->def, inputlist[1]->c.generic.data, 1.0,1.0); release_ref(inputlist[1]); inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = index; return 0; } int vis_worker_add_globalget(datum ** inputlist, queue_entry * worker_entry) { worker_datum * work = inputlist[0]->c.generic.data; int index; char * name = malloc(inputlist[1]->c.generic.len + inputlist[2]->c.generic.len + 1); memcpy(name, inputlist[1]->c.generic.data, inputlist[1]->c.generic.len); release_ref(inputlist[1]); strcat(name, "::"); strcat(name, inputlist[2]->c.generic.data); release_ref(inputlist[2]); index = add_global_get(work->def, name, 1.0,1.0); free(name); inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = index; return 0; } int vis_worker_add_globalset(datum ** inputlist, queue_entry * worker_entry) { worker_datum * work = inputlist[0]->c.generic.data; int index; char * name = malloc(inputlist[1]->c.generic.len + inputlist[2]->c.generic.len + 1); memcpy(name, inputlist[1]->c.generic.data, inputlist[1]->c.generic.len); release_ref(inputlist[1]); strcat(name, "::"); strcat(name, inputlist[2]->c.generic.data); release_ref(inputlist[2]); index = add_global_set(work->def, name, 1.0,1.0); free(name); inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = index; return 0; } int vis_worker_new(datum ** inputlist, queue_entry * worker_entry) { int i; datum * output = new_datum(BUILTIN_TYPE_WORKER, 1, sizeof(worker_datum), worker_entry->instance->def->program); worker_datum * work = output->c.generic.data; work->def = create_worker(worker_entry->instance->def->program, inputlist[0]->c.generic.data, 0, 0, USER_FLAG | WORKER_TYPE); add_program_ref(work->def->program); for(i = 0; i < 32; ++i) work->params[i] = NULL; release_ref(inputlist[0]); inputlist[0] = output; return 0; } int vis_worker_clear(datum ** inputlist, queue_entry * worker_entry) { int i; worker_datum * work = inputlist[0]->c.generic.data; VIS_EnterCriticalSection(work->def->implement_func->lock); for(i = 0; i < work->def->implement_func->num_workers; ++i) { if(work->def->implement_func->workerlist[i].type == CONSTANT) { release_ref(work->def->implement_func->workerlist[i].value_index); } } work->def->num_inputs = 0; work->def->num_outputs = 0; work->def->implement_func->num_workers = 0; work->def->implement_func->num_wires = 0; work->def->implement_func->dirty = TRUE; VIS_LeaveCriticalSection(work->def->implement_func->lock); return 0; } int vis_worker_uses(datum ** inputlist, queue_entry * worker_entry) { int i; worker_datum * work = inputlist[0]->c.generic.data; list_data * list = inputlist[1]->c.generic.data; char ** new_uses; if(list->num_entries) { new_uses = malloc(sizeof(char *) * list->num_entries); for(i = 0; i < list->num_entries; ++i) { if(list->entries[i]->company->type_id != BUILTIN_TYPE_STRING) { ERRORPUTS("List passed to Uses@Worker contains non-string value(s)\n"); execute_active = FALSE; return -1; } new_uses[i] = malloc(sizeof(char) * list->entries[i]->c.generic.len); memcpy(new_uses[i], list->entries[i]->c.generic.data, list->entries[i]->c.generic.len); } } else new_uses = NULL; if(work->def->uses_stores) free(work->def->uses_stores); work->def->uses_stores = new_uses; work->def->num_stores = list->num_entries; release_ref(inputlist[1]); return 0; } int vis_worker_setio_counts(datum ** inputlist, queue_entry * worker_entry) { int i; int new_inputs = inputlist[1]->c.integers.num_a; worker_datum * work = inputlist[0]->c.generic.data; release_ref(inputlist[1]); if(work->def->num_inputs < new_inputs) { work->def->input_types = realloc(work->def->input_types, sizeof(short)*new_inputs); for(i = work->def->num_inputs; i < new_inputs; ++i) work->def->input_types[i] = ANY_TYPE; } work->def->num_inputs = new_inputs; work->def->num_outputs = inputlist[2]->c.integers.num_a; release_ref(inputlist[2]); return 0; } int vis_program_new(datum ** inputlist, queue_entry * worker_entry) { program * prog = new_program(START_DEF_STORAGE, START_COMP_STORAGE); inputlist[0] = new_datum(BUILTIN_TYPE_PROGRAM, 2, 0, worker_entry->instance->def->program); inputlist[0]->c.generic.data = prog; inputlist[0]->c.generic.len = sizeof(program); //inputlist[0]->union_type = 1; return 0; } int vis_program_new_worker(datum ** inputlist, queue_entry * worker_entry) { int i; datum * output = new_datum(BUILTIN_TYPE_WORKER, 1, sizeof(worker_datum), worker_entry->instance->def->program); worker_datum * work = output->c.generic.data; add_program_ref(inputlist[0]->c.generic.data); work->def = create_worker(inputlist[0]->c.generic.data, inputlist[1]->c.generic.data, 0, 0, USER_FLAG | WORKER_TYPE); for(i = 0; i < 32; ++i) work->params[i] = NULL; release_ref(inputlist[1]); inputlist[1] = output; return 0; } int vis_program_add_worker(datum ** inputlist, queue_entry * worker_entry) { int i; worker_datum * work = inputlist[1]->c.generic.data; program * prog = inputlist[0]->c.generic.data; datum * output = new_datum(BUILTIN_TYPE_WORKER, 1, sizeof(worker_datum), worker_entry->instance->def->program); worker_datum * out_work = output->c.generic.data; add_program_ref(inputlist[0]->c.generic.data); out_work->def = create_worker(prog, work->def->name, work->def->num_inputs, work->def->num_outputs, WORKER_TYPE); out_work->def->implement_func = work->def->implement_func; out_work->def->type = work->def->type; if(work->def->type & USER_FLAG) out_work->def->program = work->def->program; for(i = 0; i < work->def->num_inputs; ++i) out_work->def->input_types[i] = out_work->def->input_types[i]; release_ref(inputlist[1]); inputlist[1] = output; return 0; } int vis_program_add_builtins(datum ** inputlist, queue_entry * worker_entry) { initpredefworkers((program *)inputlist[0]->c.generic.data); return 0; } int vis_program_run(datum ** inputlist, queue_entry * worker_entry) { datum * params[32]; defchunk * current; int i; program * prog = inputlist[0]->c.generic.data; params[0] = inputlist[1]; VIS_EnterCriticalSection(program_count_lock); ++program_count; VIS_LeaveCriticalSection(program_count_lock); prep_program(prog); add_program_ref(prog); init_custom_worker(-1, NULL, prog->defs->deflist, main_callback, add_ref(inputlist[0]), params); return 0; } int vis_program_find_worker(datum ** inputlist, queue_entry * worker_entry) { int i,returnval; worker_datum * work; worker_def * def; program * prog = inputlist[0]->c.generic.data; returnval = find_worker(inputlist[1]->c.generic.data, NULL, NULL, prog, &def); release_ref(inputlist[0]); if(returnval >= 0) { add_program_ref(prog); release_ref(inputlist[1]); inputlist[0] = new_datum(BUILTIN_TYPE_WORKER, 1, sizeof(worker_datum), worker_entry->instance->def->program); inputlist[1] = NULL; work = inputlist[0]->c.generic.data; work->def = def; for(i = 0; i < 32; ++i) work->params[i] = NULL; } else { inputlist[0] = NULL; } return 0; } void free_worker(worker_def * def) { int i; if(def->type & USER_FLAG && (def->type & TYPE_MASK) == WORKER_TYPE) { for(i = 0; i < def->implement_func->num_workers; ++i) if(def->implement_func->workerlist[i].type == CONSTANT) release_ref(def->implement_func->workerlist[i].value_index); free(def->implement_func->workerlist); free(def->implement_func->wirelist); free(def->implement_func->workers_to_wires_up); free(def->implement_func->workers_to_wires_down); free(def->implement_func); } free(def->name); free(def->input_types); free(def->output_types); } void free_company(company * comp) { free(comp->methodlist); free(comp->room_list); } void add_program_ref(program * prog) { VIS_EnterCriticalSection(prog->lock); ++prog->refcount; VIS_LeaveCriticalSection(prog->lock); } void release_program_ref(program * prog) { int i; defchunk * current, *temp; VIS_EnterCriticalSection(prog->lock); --prog->refcount; if(!prog->refcount) { VIS_LeaveCriticalSection(prog->lock); VIS_DeleteCriticalSection(prog->lock); current = prog->defs; while(current) { for(i = 0; i < current->num_defs; ++i) { free_worker(current->deflist + i); } current = current->next; } current = prog->defs; while(current) { temp = current; current = current->next; free(temp); } //FIXME: We can't currently free the object definitions because of issues related to global stores //for(i = 0; i < prog->num_companies; ++i) // free_company(prog->companylist + i); //free(prog->companylist); free(prog); } else { VIS_LeaveCriticalSection(prog->lock); } } /* int vis_worker_begin_transaction(datum ** inputlist, queue_entry * worker_entry) { worker_def * def; int returnval; datum * params[2]; int i; global_store * store; list_data * list = inputist[0]->c.generic.data; transaction * trans = malloc(sizeof(transaction) + list->num_entries - 1); trans->num_stores = list->num_entries; VIS_EnterCriticalSection(global_store_lock); for(i = 0; i < list->num_entries; ++i) { params[0] = global_store_dict; params[1] = add_ref(list->entries[i]); vis_dict_index(params, NULL); store = params[0]->c.generic.data; while(store->inuse) { VIS_LeaveCriticalSection(global_store_lock); #ifdef WIN32 Sleep(0); #else sleep(0); #endif VIS_EnterCriticalSection(global_store_lock); } store->inuse; trans->stores[i] = params[0]; } VIS_LeaveCriticalSection(global_store_lock; release_ref(inputlist[0]); def = deflist+inputlist[1]->c.integers.num_a; release_ref(inputlist[1]); list_to_array(inputlist[2], inputlist, def->num_inputs); returnval = execute_def_data(def, *worker_entry, inputlist, trasnaction_sub_callback, transaction); if(returnval == 0) inputlist[0] = array_to_list(inputlist, def->num_outputs); return returnval; } */