diff options
Diffstat (limited to 'system/kernel')
-rw-r--r-- | system/kernel/CONTENTS | 7 | ||||
-rw-r--r-- | system/kernel/Makefile | 16 | ||||
-rw-r--r-- | system/kernel/pdp.c | 198 | ||||
-rw-r--r-- | system/kernel/pdp_comm.c | 198 | ||||
-rw-r--r-- | system/kernel/pdp_compat.c | 56 | ||||
-rw-r--r-- | system/kernel/pdp_control.c | 186 | ||||
-rw-r--r-- | system/kernel/pdp_debug.c | 21 | ||||
-rw-r--r-- | system/kernel/pdp_dpd_command.c | 87 | ||||
-rw-r--r-- | system/kernel/pdp_forth.c | 541 | ||||
-rw-r--r-- | system/kernel/pdp_list.c | 663 | ||||
-rw-r--r-- | system/kernel/pdp_mem.c | 129 | ||||
-rw-r--r-- | system/kernel/pdp_packet.c | 957 | ||||
-rw-r--r-- | system/kernel/pdp_packet2.c | 623 | ||||
-rw-r--r-- | system/kernel/pdp_post.c | 48 | ||||
-rw-r--r-- | system/kernel/pdp_queue.c | 347 | ||||
-rw-r--r-- | system/kernel/pdp_symbol.c | 196 | ||||
-rw-r--r-- | system/kernel/pdp_type.c | 501 | ||||
-rw-r--r-- | system/kernel/pdp_type.c_old | 542 | ||||
-rw-r--r-- | system/kernel/pdp_ut.c | 262 |
19 files changed, 0 insertions, 5578 deletions
diff --git a/system/kernel/CONTENTS b/system/kernel/CONTENTS deleted file mode 100644 index c2f7c8c..0000000 --- a/system/kernel/CONTENTS +++ /dev/null @@ -1,7 +0,0 @@ -debug debug stuff -forth the forth system -list the list implementation -mem memory allocation stuf -packet the packet memory manager -type the type handling and conversion system -symbol symbol implementation, with namespaces for forth, types, classes, ... diff --git a/system/kernel/Makefile b/system/kernel/Makefile deleted file mode 100644 index f1d82a9..0000000 --- a/system/kernel/Makefile +++ /dev/null @@ -1,16 +0,0 @@ - -OBJECTS = pdp.o pdp_ut.o pdp_packet.o pdp_queue.o pdp_comm.o \ - pdp_control.o pdp_compat.o pdp_type.o pdp_dpd_command.o \ - pdp_list.o pdp_forth.o - - -include ../../Makefile.config - -all: pdp_main_clean $(OBJECTS) - -pdp_main_clean: - rm -f pdp.o - -clean: - rm -f *~ - rm -f *.o diff --git a/system/kernel/pdp.c b/system/kernel/pdp.c deleted file mode 100644 index d71e655..0000000 --- a/system/kernel/pdp.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Pure Data Packet system implementation: setup code - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "pdp_config.h" -#include "pdp.h" -#include <stdio.h> - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - -/* module setup declarations (all C-style) */ - -/* pdp system / internal stuff */ -void pdp_list_setup(void); -void pdp_sym_setup(void); -void pdp_forth_setup(void); -void pdp_type_setup(void); -void pdp_packet_setup(void); -void pdp_ut_setup(void); -void pdp_queue_setup(void); -void pdp_control_setup(void); -void pdp_image_setup(void); -void pdp_bitmap_setup(void); -void pdp_matrix_setup(void); - - -/* pdp modules */ -void pdp_xv_setup(void); -void pdp_add_setup(void); -void pdp_mul_setup(void); -void pdp_mix_setup(void); -void pdp_randmix_setup(void); -void pdp_qt_setup(void); -void pdp_v4l_setup(void); -void pdp_reg_setup(void); -void pdp_conv_setup(void); -void pdp_bq_setup(void); -void pdp_del_setup(void); -void pdp_snap_setup(void); -void pdp_trigger_setup(void); -void pdp_route_setup(void); -void pdp_noise_setup(void); -void pdp_gain_setup(void); -void pdp_chrot_setup(void); -void pdp_scope_setup(void); -void pdp_scale_setup(void); -void pdp_zoom_setup(void); -void pdp_scan_setup(void); -void pdp_scanxy_setup(void); -void pdp_sdl_setup(void); -void pdp_cheby_setup(void); -void pdp_grey2mask_setup(void); -void pdp_constant_setup(void); -void pdp_logic_setup(void); -void pdp_glx_setup(void); -void pdp_loop_setup(void); -void pdp_description_setup(void); -void pdp_convert_setup(void); -void pdp_stateless_setup(void); -void pdp_mat_mul_setup(void); -void pdp_mat_lu_setup(void); -void pdp_mat_vec_setup(void); -void pdp_plasma_setup(void); -void pdp_cog_setup(void); -void pdp_histo_setup(void); -void pdp_array_setup(void); - -/* hacks */ -void pdp_inspect_setup(void); -void pdp_slice_cut_setup(void); -void pdp_slice_glue_setup(void); - -/* testing */ -void pdp_dpd_test_setup(void); -void pdp_forthproc_setup(void); - - - -/* library setup routine */ -void pdp_setup(void){ - - /* babble */ - post ("PDP: pure data packet"); - -#ifdef PDP_VERSION - fprintf(stderr, "PDP: version " PDP_VERSION "\n"); -#endif - - - /* setup pdp system */ - pdp_list_setup(); - pdp_type_setup(); - pdp_sym_setup(); - pdp_packet_setup(); - pdp_forth_setup(); - pdp_control_setup(); - - pdp_image_setup(); - pdp_bitmap_setup(); - pdp_matrix_setup(); - - pdp_queue_setup(); - - /* setup utility toolkit */ - pdp_ut_setup(); - - /* setup pdp modules*/ - pdp_add_setup(); - pdp_mul_setup(); - pdp_mix_setup(); - pdp_randmix_setup(); - pdp_reg_setup(); - pdp_conv_setup(); - pdp_bq_setup(); - pdp_del_setup(); - pdp_snap_setup(); - pdp_trigger_setup(); - pdp_route_setup(); - pdp_noise_setup(); - pdp_plasma_setup(); - pdp_gain_setup(); - pdp_chrot_setup(); - pdp_scope_setup(); - pdp_scale_setup(); - pdp_zoom_setup(); - pdp_scan_setup(); - pdp_scanxy_setup(); - pdp_cheby_setup(); - pdp_grey2mask_setup(); - pdp_constant_setup(); - pdp_logic_setup(); - pdp_loop_setup(); - pdp_description_setup(); - pdp_convert_setup(); - pdp_stateless_setup(); - pdp_mat_mul_setup(); - pdp_mat_lu_setup(); - pdp_mat_vec_setup(); - pdp_cog_setup(); - pdp_histo_setup(); - pdp_array_setup(); - - /* experimental stuff */ - pdp_slice_cut_setup(); - pdp_slice_glue_setup(); - pdp_inspect_setup(); - - /* testing */ - //pdp_dpd_test_setup(); - pdp_forthproc_setup(); - - /* optional modules */ - -#ifdef HAVE_PDP_QT - pdp_qt_setup(); -#endif - -#ifdef HAVE_PDP_XV - pdp_xv_setup(); -#endif - -#ifdef HAVE_PDP_SDL - pdp_sdl_setup(); -#endif - -#ifdef HAVE_PDP_V4L - pdp_v4l_setup(); -#endif - -#ifdef HAVE_PDP_GLX - pdp_glx_setup(); -#endif - -} - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_comm.c b/system/kernel/pdp_comm.c deleted file mode 100644 index bcc0e3a..0000000 --- a/system/kernel/pdp_comm.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Pure Data Packet system implementation. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* this file contains misc communication (packet) methods for pd */ - - -#include "pdp.h" -#include "pdp_internals.h" -#include <stdio.h> - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - -t_symbol *_pdp_sym_pdp; -t_symbol *_pdp_sym_rro; -t_symbol *_pdp_sym_rrw; -t_symbol *_pdp_sym_prc; -t_symbol *_pdp_sym_dpd; -t_symbol *_pdp_sym_ins; -t_symbol *_pdp_sym_acc; - -t_symbol *pdp_sym_pdp() {return _pdp_sym_pdp;} -t_symbol *pdp_sym_rro() {return _pdp_sym_rro;} -t_symbol *pdp_sym_rrw() {return _pdp_sym_rrw;} -t_symbol *pdp_sym_prc() {return _pdp_sym_prc;} -t_symbol *pdp_sym_dpd() {return _pdp_sym_dpd;} -t_symbol *pdp_sym_ins() {return _pdp_sym_ins;} -t_symbol *pdp_sym_acc() {return _pdp_sym_acc;} - -/************** packet management and communication convenience functions ************/ - -/* send a packet to an outlet */ -void outlet_pdp(t_outlet *out, int packetid) -{ - t_atom atom[2]; - - SETFLOAT(atom+1, (float)packetid); - - SETSYMBOL(atom+0, pdp_sym_rro()); - outlet_anything(out, pdp_sym_pdp(), 2, atom); - - SETSYMBOL(atom+0, pdp_sym_rrw()); - outlet_anything(out, pdp_sym_pdp(), 2, atom); - - SETSYMBOL(atom+0, pdp_sym_prc()); - outlet_anything(out, pdp_sym_pdp(), 2, atom); - -} - -/* send an accumulation packet to an outlet */ -void outlet_dpd(t_outlet *out, int packetid) -{ - t_atom atom[2]; - - SETFLOAT(atom+1, (float)packetid); - - SETSYMBOL(atom+0, pdp_sym_ins()); - outlet_anything(out, pdp_sym_dpd(), 2, atom); - - SETSYMBOL(atom+0, pdp_sym_acc()); - outlet_anything(out, pdp_sym_dpd(), 2, atom); - -} - -/* unregister a packet and send it to an outlet */ -void - -pdp_packet_pass_if_valid(t_outlet *outlet, int *packet_ptr) -{ - t_pdp *header = pdp_packet_header(*packet_ptr); - //if (-1 != *packet){ - if (header){ - /* if packet is exclusively owned, mark as passing */ - if (1 == header->users) pdp_packet_mark_passing(packet_ptr); - - /* send */ - outlet_pdp(outlet, *packet_ptr); - - /* if the packet is still here (was passing and not registered, - or it was a shared copy): unregister it */ - if (-1 != *packet_ptr){ - pdp_packet_unmark_passing(*packet_ptr); - pdp_packet_mark_unused(*packet_ptr); - *packet_ptr = -1; - } - } -} - -void -pdp_packet_replace_if_valid(int *dpacket, int *spacket) -{ - if (-1 != *spacket){ - pdp_packet_mark_unused(*dpacket); - *dpacket = *spacket; - *spacket = -1; - } - -} - - -int -pdp_packet_copy_ro_or_drop(int *dpacket, int spacket) -{ - int drop = 0; - if (*dpacket == -1) *dpacket = pdp_packet_copy_ro(spacket); - else { - /* send a notification there is a dropped packet */ - pdp_control_notify_drop(spacket); - drop = 1; - } - return drop; -} - - -int -pdp_packet_copy_rw_or_drop(int *dpacket, int spacket) -{ - int drop = 0; - if (*dpacket == -1) *dpacket = pdp_packet_copy_rw(spacket); - else { - /* send a notification there is a dropped packet */ - pdp_control_notify_drop(spacket); - drop = 1; - } - return drop; -} - -int -pdp_packet_convert_ro_or_drop(int *dpacket, int spacket, t_pdp_symbol *template) -{ - int drop = 0; - - if (!template) return pdp_packet_copy_ro_or_drop(dpacket, spacket); - - if (*dpacket == -1) *dpacket = pdp_packet_convert_ro(spacket, template); - else { - /* send a notification there is a dropped packet */ - pdp_control_notify_drop(spacket); - drop = 1; - } - return drop; -} - - -int -pdp_packet_convert_rw_or_drop(int *dpacket, int spacket, t_pdp_symbol *template) -{ - int drop = 0; - - if (!template) return pdp_packet_copy_rw_or_drop(dpacket, spacket); - - if (*dpacket == -1) *dpacket = pdp_packet_convert_rw(spacket, template); - else { - /* send a notification there is a dropped packet */ - pdp_control_notify_drop(spacket); - drop = 1; - } - return drop; -} - - -void -pdp_sym_setup(void) -{ - _pdp_sym_pdp = gensym("pdp"); - _pdp_sym_rro = gensym("register_ro"); - _pdp_sym_rrw = gensym("register_rw"); - _pdp_sym_prc = gensym("process"); - _pdp_sym_dpd = gensym("dpd"); - _pdp_sym_ins = gensym("inspect"); - _pdp_sym_acc = gensym("accumulate"); -} - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_compat.c b/system/kernel/pdp_compat.c deleted file mode 100644 index 4bcf00d..0000000 --- a/system/kernel/pdp_compat.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Pure Data Packet system implementation. Compatibility routines. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* this file contains misc communication methods */ - - -#include "pdp.h" -#include "pdp_internals.h" -#include <stdio.h> - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - - - -void -pdp_pass_if_valid(t_outlet *outlet, int *packet) -{ - pdp_packet_pass_if_valid(outlet, packet); -} - -void -pdp_replace_if_valid(int *dpacket, int *spacket) -{ - pdp_packet_replace_if_valid(dpacket, spacket); - -} - - - - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_control.c b/system/kernel/pdp_control.c deleted file mode 100644 index 2cba7b7..0000000 --- a/system/kernel/pdp_control.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Pure Data Packet system implementation: control object - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* this is an actual pd class that is used for communication with the - pdp framework */ - -#include "pdp.h" -#include "pdp_internals.h" -#include "pdp_control.h" -#include <stdio.h> - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - - - -static long dropped_packets; - -static t_class* pdp_control_class; - - -/* pdp control instance data */ - -struct _pdp_control; -typedef struct _pdp_control -{ - t_object x_obj; - t_outlet *x_outlet0; - struct _pdp_control *x_next; - -} t_pdp_control; - - - -static t_pdp_control *pdp_control_list; - -static void pdp_control_info(t_pdp_control *x) -{ -} - -static void pdp_control_collectgarbage(t_pdp_control *x) -{ - int nb_packets_freed = pdp_pool_collect_garbage(); - post("pdp_control: freed %d packets", nb_packets_freed); - -} - -static void pdp_control_set_mem_limit(t_pdp_control *x, t_floatarg f) -{ - int limit = (int)f; - if (limit < 0) limit = 0; - pdp_pool_set_max_mem_usage(limit); - if (limit) post("pdp_control: set memory limit to %d bytes", limit); - else post("pdp_control: disabled memory limit"); - -} - -static void pdp_control_thread(t_pdp_control *x, t_floatarg f) -{ - int t = (int)f; - - if (t){ - post("pdp_control: pdp is now using its own processing thread"); - pdp_queue_use_thread(1); - } - else { - post("pdp_control: pdp is now using the main pd thread"); - pdp_queue_use_thread(0); - } -} - - -static void pdp_control_send_drop_message(t_pdp_control *x) -{ - t_atom atom[1]; - t_symbol *s = gensym("pdp_drop"); - - SETFLOAT(atom+0, (float)dropped_packets); - outlet_anything(x->x_outlet0, s, 1, atom); -} - - -static void pdp_control_free(t_pdp_control *x) -{ - /* remove from linked list */ - t_pdp_control *curr = pdp_control_list; - if (pdp_control_list == x) pdp_control_list = x->x_next; - else while (curr){ - if (curr->x_next == x) { - curr->x_next = x->x_next; - break; - } - else { - curr = curr->x_next; - } - - } -} - - -static void *pdp_control_new(void) -{ - t_pdp_control *x = (t_pdp_control *)pd_new(pdp_control_class); - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - - /* add to list */ - x->x_next = pdp_control_list; - pdp_control_list = x; - return x; -} - -/************************* class methods ***************************************/ - - -void pdp_control_addmethod(t_method m, t_symbol *s) -{ - class_addmethod(pdp_control_class, m, s, A_GIMME, A_NULL); -} - -void pdp_control_setup(void) -{ - - pdp_control_list = 0; - dropped_packets = 0; - - /* setup pd class data */ - pdp_control_class = class_new(gensym("pdp_control"), (t_newmethod)pdp_control_new, - (t_method)pdp_control_free, sizeof(t_pdp_control), 0, A_NULL); - - - class_addmethod(pdp_control_class, (t_method)pdp_control_info, gensym("info"), A_NULL); - class_addmethod(pdp_control_class, (t_method)pdp_control_thread, gensym("thread"), A_DEFFLOAT, A_NULL); - class_addmethod(pdp_control_class, (t_method)pdp_control_collectgarbage, gensym("collectgarbage"), A_NULL); - class_addmethod(pdp_control_class, (t_method)pdp_control_set_mem_limit, gensym("memlimit"), A_FLOAT, A_NULL); -} - - - -void pdp_control_notify_broadcast(t_pdp_control_method_notify *notify) -{ - t_pdp_control *curr = pdp_control_list; - while (curr){ - (*notify)(curr); - curr = curr->x_next; - } -} - - - -/************************* notify class methods *************************/ - -void pdp_control_notify_drop(int packet) -{ - dropped_packets++; - - /* send drop notify to controller class instances */ - pdp_control_notify_broadcast(pdp_control_send_drop_message); - //post("dropped packet"); -} - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_debug.c b/system/kernel/pdp_debug.c deleted file mode 100644 index 07f6541..0000000 --- a/system/kernel/pdp_debug.c +++ /dev/null @@ -1,21 +0,0 @@ -#include <sys/types.h> -#include <signal.h> -#include <unistd.h> -#include "pdp_post.h" - -int pdp_debug_sigtrap_on_assert; - - -void pdp_assert_hook (char *condition, char *file, int line) -{ - pdp_post("PDP_ASSERT (%s) failed in file %s, line %u. ", condition, file, line); - pdp_post("%s.\n", pdp_debug_sigtrap_on_assert ? "sending SIGTRAP" : "continuing"); - - if (pdp_debug_sigtrap_on_assert) kill(getpid(), SIGTRAP); -} - - -void pdp_debug_setup(void) -{ - pdp_debug_sigtrap_on_assert = 1; -} diff --git a/system/kernel/pdp_dpd_command.c b/system/kernel/pdp_dpd_command.c deleted file mode 100644 index 0d3ecf1..0000000 --- a/system/kernel/pdp_dpd_command.c +++ /dev/null @@ -1,87 +0,0 @@ - -/* - * Pure Data Packet header file. DPD command class - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* this object implements a dpd command queue and command object */ - -#include "pdp.h" -#include "pdp_dpd_command.h" - -void pdp_dpd_commandfactory_init(t_pdp_dpd_commandfactory *x, u32 size) -{ - x->nb_commands = 0; - x->command_size = size; - x->command = 0; -} - -void _pdp_dpd_commandfactory_free(t_pdp_dpd_command *x) -{ - if (x) _pdp_dpd_commandfactory_free(x->next); - pdp_dealloc(x); -} - -void pdp_dpd_commandfactory_free(t_pdp_dpd_commandfactory *x) -{ - _pdp_dpd_commandfactory_free(x->command); - x->command = 0; - x->nb_commands = 0; -} - - -/* factory method */ -t_pdp_dpd_command *pdp_dpd_commandfactory_get_new_command(t_pdp_dpd_commandfactory *x) -{ - - t_pdp_dpd_command *c = x->command; - t_pdp_dpd_command *oldhead = c; - - /* check if we can reuse */ - while (c){ - if (!c->used){ - c->used = 1; - //post("reusing command %x", c, c->used); - return c; - } - //post("command %x is used %d", c, c->used); - c = c->next; - } - - /* create a new command */ - x->command = (t_pdp_dpd_command *)pdp_alloc(x->command_size); - x->command->next = oldhead; - x->command->used = 1; - x->nb_commands++; - //post("created command %x, nbcommands: %d", x->command, x->nb_commands); - return x->command; - -} - - -/* (self)destructor */ -void pdp_dpd_command_suicide(void *x) -{ - t_pdp_dpd_command *c = (t_pdp_dpd_command *)x; - c->used = 0; - //post("command %x committed suicide %d", c, c->used); -} - - - - diff --git a/system/kernel/pdp_forth.c b/system/kernel/pdp_forth.c deleted file mode 100644 index 1764004..0000000 --- a/system/kernel/pdp_forth.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Pure Data Packet header file. Packet processor system - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <stdlib.h> -#include <math.h> -#include "pdp.h" -#include "pdp_forth.h" - -#define D if (0) - - - -t_pdp_stack *pdp_stack_new(void) {return pdp_list_new(0);} - -void pdp_stack_free(t_pdp_stack *s) { - pdp_tree_strip_packets(s); - pdp_list_free(s); -} - - -/* some stack manips */ -t_pdp_word_error pdp_stack_dup(t_pdp_stack *s) -{ - if (!s->first) return e_underflow; - pdp_list_add(s, s->first->t, s->first->w); - - /* copy it properly if its a packet */ - if (s->first->t == a_packet){ - s->first->w.w_packet = pdp_packet_copy_ro(s->first->w.w_packet); - } - return e_ok; -} - -t_pdp_word_error pdp_stack_drop(t_pdp_stack *s) -{ - if (!s->first) return e_underflow; - - /* delete it properly if its a packet */ - if (s->first->t == a_packet){ - pdp_packet_mark_unused(s->first->w.w_packet); - } - pdp_list_pop(s); - - return e_ok; -} - -t_pdp_word_error pdp_stack_over(t_pdp_stack *s) -{ - if (s->elements < 2) return e_underflow; - pdp_list_add(s, s->first->next->t, s->first->next->w); - - /* copy it properly if its a packet */ - if (s->first->t == a_packet){ - s->first->w.w_packet = pdp_packet_copy_ro(s->first->w.w_packet); - } - - return e_ok; -} - -t_pdp_word_error pdp_stack_swap(t_pdp_stack *s) -{ - t_pdp_word w; - t_pdp_word_type t; - if (s->elements < 2) return e_underflow; - w = s->first->w; - t = s->first->t; - s->first->w = s->first->next->w; - s->first->t = s->first->next->t; - s->first->next->w = w; - s->first->next->t = t; - return e_ok; - -} - -/* pushing and popping the stack */ - -t_pdp_word_error pdp_stack_push_float(t_pdp_stack *s, float f) {pdp_list_add(s, a_float, (t_pdp_word)f); return e_ok;} -t_pdp_word_error pdp_stack_push_int(t_pdp_stack *s, int i) {pdp_list_add(s, a_int, (t_pdp_word)i); return e_ok;} -t_pdp_word_error pdp_stack_push_pointer(t_pdp_stack *s, void *x) {pdp_list_add(s, a_pointer, (t_pdp_word)x); return e_ok;} -t_pdp_word_error pdp_stack_push_symbol(t_pdp_stack *s, t_pdp_symbol *x) {pdp_list_add(s, a_symbol, (t_pdp_word)x); return e_ok;} - -/* note: packets pushed stack are owned by the stack. if a caller wants to keep a packet that - will be deleted by the word, it should make a copy before transferring it to the stack. - if a stack processor wants to write to a packet, it should replace it with a writable copy first */ - -t_pdp_word_error pdp_stack_push_packet(t_pdp_stack *s, int p) {pdp_list_add(s, a_packet, (t_pdp_word)p); return e_ok;} - - - - - -t_pdp_word_error pdp_stack_pop_float(t_pdp_stack *s, float *f) -{ - if (!s->first) return e_underflow; - - if (s->first->t == a_float) *f = s->first->w.w_float; - else if (s->first->t == a_int) *f = (float)s->first->w.w_int; - else *f = 0.0f; - pdp_stack_drop(s); - return e_ok; -} - -t_pdp_word_error pdp_stack_pop_int(t_pdp_stack *s, int *i) -{ - if (!s->first) return e_underflow; - if (s->first->t == a_int) *i = s->first->w.w_int; - else if (s->first->t == a_float) *i = (int)s->first->w.w_float; - else *i = 0; - pdp_stack_drop(s); - return e_ok; -} - -t_pdp_word_error pdp_stack_pop_pointer(t_pdp_stack *s, void **x) -{ - if (!s->first) return e_underflow; - *x = (s->first->t == a_pointer) ? s->first->w.w_pointer : 0; - pdp_stack_drop(s); - return e_ok; -} - -t_pdp_word_error pdp_stack_pop_symbol(t_pdp_stack *s, t_pdp_symbol **x) -{ - if (!s->first) return e_underflow; - *x = (s->first->t == a_symbol) ? s->first->w.w_symbol : pdp_gensym("invalid"); - pdp_stack_drop(s); - return e_ok; -} - -/* packets popped from the stack are owned by the caller */ - -t_pdp_word_error pdp_stack_pop_packet(t_pdp_stack *s, int *p) -{ - if (!s->first) return e_underflow; - *p = (s->first->t == a_packet) ? s->first->w.w_packet : -1; - pdp_list_pop(s); //ownership is transferred to receiver, drop kills the packet - return e_ok; -} - - -t_pdp_word_error pdp_stack_mov(t_pdp_stack *s) -{ - int position; - t_pdp_atom *a, *a_before; - if (s->elements < 2) return e_underflow; - if (s->first->t != a_int) return e_type; - - pdp_stack_pop_int(s, &position); // get insert point - if (position < 1) return e_ok; // < 0 : invalid; do nothing, 0 : nop (= insert at start, but already at start) - if ((s->elements-1) < position) return e_underflow; - - a = s->first; // get first atom - s->first = a->next; - - if (s->elements-1 == position){ //insert at end - s->last->next = a; - a->next = 0; - s->last = a; - } - else { //insert somewhere in the middle - a_before = s->first; - while (--position) a_before = a_before->next; - a->next = a_before->next; - a_before->next = a; - } - return e_ok; -} - -/* rotate stack down (tos -> bottom) */ -t_pdp_word_error pdp_stack_rdown(t_pdp_stack *s) -{ - t_pdp_word_type t = s->first->t; - t_pdp_word w = s->first->w; - pdp_list_pop(s); - pdp_list_add_back(s, t, w); - return e_ok; -} - - -/* convert to int */ -t_pdp_word_error pdp_stack_int(t_pdp_stack *s) -{ - int i; - pdp_stack_pop_int(s, &i); - pdp_stack_push_int(s, i); - return e_ok; -} - -/* convert to float */ -t_pdp_word_error pdp_stack_float(t_pdp_stack *s) -{ - float f; - pdp_stack_pop_float(s, &f); - pdp_stack_push_float(s, f); - return e_ok; -} - - -#define OP1(name, type, op) \ -t_pdp_word_error pdp_stack_##name##_##type (t_pdp_stack *s) \ -{ \ - type x0; \ - pdp_stack_pop_##type (s, &(x0)); \ - pdp_stack_push_##type (s, op (x0)); \ - return e_ok; \ -} - -#define OP2(name, type, op) \ -t_pdp_word_error pdp_stack_##name##_##type (t_pdp_stack *s) \ -{ \ - type x0, x1; \ - pdp_stack_pop_##type (s, &(x0)); \ - pdp_stack_pop_##type (s, &(x1)); \ - pdp_stack_push_##type (s, x1 op x0); \ - return e_ok; \ -} - -/* some floating point and integer stuff */ - -OP2(add, float, +); -OP2(sub, float, -); -OP2(mul, float, *); -OP2(div, float, /); - -OP1(sin, float, sin); -OP1(cos, float, cos); - -OP2(add, int, +); -OP2(sub, int, -); -OP2(mul, int, *); -OP2(div, int, /); -OP2(mod, int, %); - -OP2(and, int, &); -OP2(or, int, |); -OP2(xor, int, ^); - - -/* some integer stuff */ - -t_pdp_word_error pdp_stack_push_invalid_packet(t_pdp_stack *s) -{ - pdp_stack_push_packet(s, -1); - return e_ok; -} - -/* dictionary manipulation */ - -void pdp_forth_word_print_debug(t_pdp_symbol *s) -{ - t_pdp_atom *a; - if (!s->s_word_spec){ - post("%s is not a forth word", s->s_name); - } - else{ - post(""); - post("forth word %s", s->s_name); - post("\tinput: %d", s->s_word_spec->input_size); - post("\toutput: %d", s->s_word_spec->output_size); - post("\ttype index: %d", s->s_word_spec->type_index); - - post("\nimplementations:"); - for(a=s->s_word_spec->implementations->first; a; a=a->next){ - t_pdp_forthword_imp *i = a->w.w_pointer; - startpost("\t%s\t", i->type ? i->type->s_name : "anything"); - pdp_list_print(i->def); - - } - post(""); - } -} - -/* add a definition (list of high level words (symbols) or primitive routines) */ -void pdp_forthdict_add_word(t_pdp_symbol *name, t_pdp_list *def, int input_size, int output_size, - int type_index, t_pdp_symbol *type) -{ - t_pdp_forthword_spec *spec = 0; - t_pdp_forthword_imp *imp = 0; - t_pdp_forthword_imp *old_imp = 0; - t_pdp_atom *a; - /* check if the word complies to a previously defined word spec with the same name */ - if (spec = name->s_word_spec){ - if ((spec->input_size != input_size) - ||(spec->output_size != output_size) - ||(spec->type_index != type_index)){ - post("ERROR: pdp_forthdict_add_word: new implementation of [%s] does not comply to old spec", - name->s_name); - return; - } - - } - /* no previous word spec with this name, so create a new spec */ - else{ - spec = name->s_word_spec = (t_pdp_forthword_spec *)pdp_alloc(sizeof(t_pdp_forthword_spec)); - spec->name = name; - spec->input_size = input_size; - spec->output_size = output_size; - spec->type_index = type_index; - spec->implementations = pdp_list_new(0); - } - - /* create the new implementation and add it */ - imp = (t_pdp_forthword_imp *)pdp_alloc(sizeof(t_pdp_forthword_imp)); - imp->name = name; - imp->def = def; - imp->type = type; - - /* can't delete old implemetations because of thread safety */ - pdp_list_add_pointer(spec->implementations, imp); - -} - -/* add a primitive */ -void pdp_forthdict_add_primitive(t_pdp_symbol *name, t_pdp_forthword w, int input_size, int output_size, - int type_index, t_pdp_symbol *type) -{ - t_pdp_list *def = pdp_list_new(1); - def->first->t = a_pointer; - def->first->w.w_pointer = w; - pdp_forthdict_add_word(name, def, input_size, output_size, type_index, type); -} - -/* parse a new definition from a null terminated string */ -t_pdp_list *pdp_forth_compile_def(char *chardef) -{ - t_pdp_list *l; - char *c; - - if (!(l = pdp_list_from_cstring(chardef, &c))){ - post ("ERROR: pdp_forth_compile_def: parse error parsing: %s", chardef); - if (*c) post ("ERROR: remaining input: %s", c); - } - if (*c){ - post ("WARNING: pdp_forth_compile_def: parsing: %s", chardef); - if (*c) post ("garbage at end of string: %s", c); - } - - return l; - -} - -void pdp_forthdict_compile_word(t_pdp_symbol *name, char *chardef, int input_size, int output_size, - int type_index, t_pdp_symbol *type) -{ - /* add the definition list to the dictionary */ - t_pdp_list *def; - - if (def = pdp_forth_compile_def (chardef)) - pdp_forthdict_add_word(name, def, input_size, output_size, type_index, type); - - -} - - - -/* execute a definition list - a def list is a list of primitives, immediates or symbolic words */ -t_pdp_word_error pdp_forth_execute_def(t_pdp_stack *stack, t_pdp_list *def) -{ - t_pdp_atom *a; - t_pdp_word_error e; - t_pdp_forthword w; - float f; - int i,p; - - D post("pdp_forth_execute_def %x %x", stack, def); - D pdp_list_print(def); - - for (a = def->first; a; a=a->next){ - switch(a->t){ - case a_float: // an immidiate float - f = a->w.w_float; - D post("pushing %f onto the stack", f); - pdp_stack_push_float(stack, f); - break; - case a_int: // an immidiate int - i = a->w.w_int; - D post("pushing %d onto the stack", i); - pdp_stack_push_int(stack, i); - break; - case a_packet: // an immidiate int - p = a->w.w_packet; - D post("pushing packet %d onto the stack", p); - pdp_stack_push_packet(stack, pdp_packet_copy_ro(p)); - break; - case a_symbol: // a high level word or an immediate symbol - D post("interpeting symbol %s", a->w.w_symbol->s_name); - if (e = pdp_forth_execute_word(stack, a->w.w_symbol)) return e; - break; - case a_pointer: // a primitive - w = a->w.w_pointer; - D post("exec primitive %x", w); - if (e = (w(stack))) return e; - break; - default: - return e_internal; - - } - } - return e_ok; -} - -/* execute a symbol (a high level word or an immediate) - this routine does the type based word multiplexing and stack checking */ -t_pdp_word_error pdp_forth_execute_word(t_pdp_stack *stack, t_pdp_symbol *word) -{ - t_pdp_symbol *type = 0; - t_pdp_atom *a; - t_pdp_forthword_spec *spec; - t_pdp_forthword_imp *imp = 0; - int i; - - D post("pdp_forth_execute_word %x %x", stack, word); - - /* first check if the word is defined. if not, the symbol will be loaded - onto the stack as an immidiate symbol */ - - if (!(spec = word->s_word_spec)){ - D post ("pushing symbol %s on the stack", word->s_name); - pdp_stack_push_symbol(stack, word); - return e_ok; - } - - D post("exec high level word [%s]", word->s_name); - - /* it is a word. check the stack size */ - if (stack->elements < spec->input_size){ - D post ("error executing [%s]: stack underflow", word->s_name); - return e_underflow; - } - - /* if the word is type oblivious, symply execute the first (only) - implementation in the list */ - if (spec->type_index < 0){ - D post("exec type oblivious word [%s]", word->s_name); - imp = spec->implementations->first->w.w_pointer; - return pdp_forth_execute_def(stack , imp->def); - } - - /* if it is not type oblivious, find the type template - to determine the correct implementation */ - - for(i=spec->type_index,a=stack->first; i--; a=a->next); - switch (a->t){ - /* get type description from first item on*/ - case a_packet: - type = pdp_packet_get_description(a->w.w_packet); break; - case a_symbol: - type = a->w.w_symbol; break; - case a_float: - type = pdp_gensym("float"); break; - case a_int: - type = pdp_gensym("int"); break; - case a_pointer: - type = pdp_gensym("pointer"); break; - default: - /* no type description found on top of stack. */ - type = pdp_gensym("unknown"); - break; - } - - /* scan the implementation list until a definition with matching type is found - if the type spec for a word is NULL, it counts as a match (for generic words) */ - for (a = spec->implementations->first; a; a = a->next){ - imp = a->w.w_pointer; - if ((!imp->type) || pdp_type_description_match(type, imp->type)){ - return pdp_forth_execute_def(stack , imp->def); - } - } - D post("ERROR: pdp_forth_execute_word: type error executing [%s] (2). stack:",word->s_name); - D pdp_list_print(stack); - - return e_type; // type error - -} - - -static void _add_2op(char *name, t_pdp_forthword w, char *type){ - pdp_forthdict_add_primitive(pdp_gensym(name), w, 2, 1, 0, pdp_gensym(type)); -} - -static void _add_1op(char *name, t_pdp_forthword w, char *type){ - pdp_forthdict_add_primitive(pdp_gensym(name), w, 1, 1, 0, pdp_gensym(type)); -} - - -void pdp_forth_setup(void) -{ - - /* add type oblivious (type_index = -1, type = NULL) stack manip primitives */ - pdp_forthdict_add_primitive(pdp_gensym("dup"), (t_pdp_forthword)pdp_stack_dup, 1, 2, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("swap"), (t_pdp_forthword)pdp_stack_swap, 2, 2, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("drop"), (t_pdp_forthword)pdp_stack_drop, 1, 0, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("over"), (t_pdp_forthword)pdp_stack_over, 2, 3, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("mov"), (t_pdp_forthword)pdp_stack_mov, 2, 1, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("down"), (t_pdp_forthword)pdp_stack_rdown, 1, 1, -1, 0); - - /* type converters (casts) */ - pdp_forthdict_add_primitive(pdp_gensym("int"), (t_pdp_forthword)pdp_stack_int, 1, 1, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("float"), (t_pdp_forthword)pdp_stack_float, 1, 1, -1, 0); - - /* add floating point ops */ - _add_2op("add", (t_pdp_forthword)pdp_stack_add_float, "float"); - _add_2op("sub", (t_pdp_forthword)pdp_stack_sub_float, "float"); - _add_2op("mul", (t_pdp_forthword)pdp_stack_mul_float, "float"); - _add_2op("div", (t_pdp_forthword)pdp_stack_div_float, "float"); - - _add_1op("sin", (t_pdp_forthword)pdp_stack_sin_float, "float"); - _add_1op("cos", (t_pdp_forthword)pdp_stack_cos_float, "float"); - - /* add integer ops */ - _add_2op("add", (t_pdp_forthword)pdp_stack_add_int, "int"); - _add_2op("sub", (t_pdp_forthword)pdp_stack_sub_int, "int"); - _add_2op("mul", (t_pdp_forthword)pdp_stack_mul_int, "int"); - _add_2op("div", (t_pdp_forthword)pdp_stack_div_int, "int"); - _add_2op("mod", (t_pdp_forthword)pdp_stack_mod_int, "int"); - - _add_2op("and", (t_pdp_forthword)pdp_stack_and_int, "int"); - _add_2op("or", (t_pdp_forthword)pdp_stack_or_int, "int"); - _add_2op("xor", (t_pdp_forthword)pdp_stack_xor_int, "int"); - - /* some immidiates */ - pdp_forthdict_add_primitive(pdp_gensym("ip"), (t_pdp_forthword)pdp_stack_push_invalid_packet, 0, 1, -1, 0); - -} diff --git a/system/kernel/pdp_list.c b/system/kernel/pdp_list.c deleted file mode 100644 index ed2ad76..0000000 --- a/system/kernel/pdp_list.c +++ /dev/null @@ -1,663 +0,0 @@ - -/* - * Pure Data Packet header file. List class - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* who can live without a list, hmm? */ - -/* rethink the list of list thing: - should free and copy really copy the lists, or should - references to lists be allowed too? - - maybe references to lists as generic pointers? */ - -#include "pdp_list.h" -#include "pdp_types.h" -#include "pdp.h" -#include <pthread.h> -#include <stdlib.h> - -#define D if (0) - -#define PDP_LIST_BLOCKSIZE 4096 - -#define PDP_ATOM_ALLOC _pdp_atom_reuse -#define PDP_ATOM_DEALLOC _pdp_atom_save -//#define PDP_ATOM_ALLOC _pdp_atom_alloc -//#define PDP_ATOM_DEALLOC _pdp_atom_dealloc - -static t_pdp_atom *freelist; -static t_pdp_list *blocklist; -static pthread_mutex_t mut; - -/* memory allocation (for ease of wrapping) */ -static inline t_pdp_list* _pdp_list_alloc(void){return (t_pdp_list *)pdp_alloc(sizeof(t_pdp_list));} -static inline void _pdp_list_dealloc(t_pdp_list *list){pdp_dealloc(list);} -static inline t_pdp_atom* _pdp_atom_alloc(void){return (t_pdp_atom *)pdp_alloc(sizeof(t_pdp_atom));} -static inline void _pdp_atom_dealloc(t_pdp_atom *a){pdp_dealloc(a);} - - - -/* some private helper methods */ - -/* list pool setup */ -void pdp_list_setup(void) -{ - freelist = 0; - blocklist = _pdp_list_alloc(); - blocklist->elements = 0; - blocklist->first = 0; - pthread_mutex_init(&mut, NULL); - -#if 0 - { - char *c = "(test 1 2 (23 4)) (een (zes (ze)ven ()))) (())"; - while (*c){ - t_pdp_list *l = pdp_list_from_char(c, &c); - if (l) pdp_list_print(l); - else{ - post("parse error: remaining input: %s", c); break; - } - } - } -#endif - -} - -/* allocate a block */ -static t_pdp_atom* _pdp_atom_block_alloc(int size) -{ - int i = size; - t_pdp_atom *atom_block, *atom; - atom_block = (t_pdp_atom *)pdp_alloc(sizeof(t_pdp_atom) * size); - atom = atom_block; - while(i--){ - atom->next = atom + 1; - atom->t = a_undef; - atom->w.w_int = 0; - atom++; - } - atom_block[size-1].next = 0; - return atom_block; -} - -static void _pdp_atomlist_fprint(FILE* f, t_pdp_atom *a); - -static void _pdp_atom_refill_freelist(void) -{ - t_pdp_atom *atom; - - if (freelist != 0) post("ERROR:_pdp_atom_do_reuse: freelist != 0"); - - /* get a new block */ - freelist = _pdp_atom_block_alloc(PDP_LIST_BLOCKSIZE); - //post("new block"); - //_pdp_atomlist_fprint(stderr, freelist); - - /* take the first element from the block to serve as a blocklist element */ - atom = freelist; - atom->t = a_pointer; - atom->w.w_pointer = freelist; - freelist = freelist->next; - atom->next = blocklist->first; - blocklist->first = atom; - blocklist->elements++; - -} - - -/* reuse an old element from the freelist, or allocate a new block */ -static inline t_pdp_atom* _pdp_atom_reuse(void) -{ - t_pdp_atom *atom; - - pthread_mutex_lock(&mut); - - while (!(atom = freelist)){ - _pdp_atom_refill_freelist(); - } - /* delete the element from the freelist */ - freelist = freelist->next; - atom->next = 0; - - pthread_mutex_unlock(&mut); - - return atom; -} - -static inline void _pdp_atom_save(t_pdp_atom *atom) -{ - pthread_mutex_lock(&mut); - - atom->next = freelist; - freelist = atom; - - pthread_mutex_unlock(&mut); -} - - - - - - -/* create a list */ -t_pdp_list* pdp_list_new(int elements) -{ - t_pdp_atom *a = 0; - t_pdp_list *l = _pdp_list_alloc(); - l->elements = 0; - if (elements){ - a = PDP_ATOM_ALLOC(); - l->elements++; - a->t = a_undef; - a->w.w_int = 0; - a->next = 0; - elements--; - } - l->first = a; - l->last = a; - - while (elements--){ - a = PDP_ATOM_ALLOC(); - l->elements++; - a->t = a_undef; - a->w.w_int = 0; - a->next = l->first; - l->first = a; - } - return l; -} - -/* clear a list */ -void pdp_list_clear(t_pdp_list *l) -{ - t_pdp_atom *a = l->first; - t_pdp_atom *next_a; - - while(a){ - next_a = a->next; - PDP_ATOM_DEALLOC(a); - a = next_a; - } - l->first = 0; - l->last = 0; - l->elements = 0; -} - -/* destroy a list */ -void pdp_list_free(t_pdp_list *l) -{ - if (l){ - pdp_list_clear(l); - _pdp_list_dealloc(l); - } -} - - -/* destroy a (sub)tree */ -void pdp_tree_free(t_pdp_list *l) -{ - if (l) { - pdp_tree_clear(l); - _pdp_list_dealloc(l); - } -} - -/* clear a tree */ -void pdp_tree_clear(t_pdp_list *l) -{ - t_pdp_atom *a = l->first; - t_pdp_atom *next_a; - - while(a){ - if (a->t == a_list) pdp_tree_free(a->w.w_list); - next_a = a->next; - PDP_ATOM_DEALLOC(a); - a = next_a; - } - l->first = 0; - l->last = 0; - l->elements = 0; -} - - -static inline int _is_whitespace(char c){return (c == ' ' || c == '\n' || c == '\t');} -static inline void _skip_whitespace(char **c){while (_is_whitespace(**c)) (*c)++;} -static inline int _is_left_separator(char c) {return (c == '(');} -static inline int _is_right_separator(char c) {return (c == ')');} -static inline int _is_separator(char c) {return (_is_left_separator(c) || _is_right_separator(c) || _is_whitespace(c));} - - -static inline void _parse_atom(t_pdp_word_type *t, t_pdp_word *w, char *c, int n) -{ - char tmp[n+1]; - //post("_parse_atom(%d, %x, %s, %d)", *t, w, c, n); - strncpy(tmp, c, n); - tmp[n] = 0; - - - /* check if it's a number */ - if (tmp[0] >= '0' && tmp[0] <= '9'){ - int is_float = 0; - char *t2; - for(t2 = tmp; *t2; t2++){ - if (*t2 == '.') { - is_float = 1; - break; - } - } - /* it's a float */ - if (is_float){ - float f = strtod(tmp, 0); - D post("adding float %f", f); - *t = a_float; - *w = (t_pdp_word)f; - } - - /* it's an int */ - else { - int i = strtol(tmp, 0, 0); - D post("adding int %d", i); - *t = a_int; - *w = (t_pdp_word)i; - } - - } - /* it's a symbol */ - else { - D post("adding symbol %s", tmp); - *t = a_symbol; - *w = (t_pdp_word)pdp_gensym(tmp); - } - - D post("done parsing atom"); - -} - - -/* create a list from a character string */ -t_pdp_list *pdp_list_from_cstring(char *chardef, char **nextchar) -{ - t_pdp_list *l = pdp_list_new(0); - char *c = chardef; - char *lastname = c; - int n = 0; - - D post ("creating list from char: %s", chardef); - - /* find opening parenthesis and skip it*/ - _skip_whitespace(&c); - if (!_is_left_separator(*c)) goto error; else c++; - - /* start counting at the first non-whitespace - character after opening parenthesis */ - _skip_whitespace(&c); - lastname = c; - n = 0; - - while(*c){ - if (!_is_separator(*c)){ - /* item not terminated: keep counting */ - c++; - n++; - } - else { - /* separator encountered whitespace or parenthesis */ - - if (n){ - /* if there was something between this and the previous - separator, we've found and atom and parse it */ - pdp_list_add_back(l, a_undef, (t_pdp_word)0); - _parse_atom(&l->last->t, &l->last->w, lastname, n); - - /* skip the whitespace after the parsed word, if any */ - _skip_whitespace(&c); - } - - /* if we're at a right separator, we're done */ - if (_is_right_separator(*c)) {c++; goto done;} - - /* if it's a left separater, we have a sublist */ - if (_is_left_separator(*c)){ - t_pdp_list *sublist = pdp_list_from_cstring(c, &c); - if (!sublist) goto error; //sublist had parse error - pdp_list_add_back(l, a_list, (t_pdp_word)sublist); - } - - /* prepare for next atom */ - lastname = c; - n = 0; - } - - } - - error: - /* end of string encountered: parse error */ - D post("parse error: %s", c); - if (nextchar) *nextchar = c; - pdp_tree_free(l); //this will free all sublists too - return 0; - - - done: - _skip_whitespace(&c); - if (nextchar) *nextchar = c; - return l; - - - -} - - -/* traversal */ -void pdp_list_apply(t_pdp_list *l, t_pdp_atom_method m) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next) m(a); -} - -void pdp_tree_apply(t_pdp_list *l, t_pdp_atom_method m) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == a_list) pdp_tree_apply(a->w.w_list, m); - else m(a); - } -} - -void pdp_list_apply_word_method(t_pdp_list *l, - t_pdp_word_type type, t_pdp_word_method wm) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == type) wm(a->w); - } -} -void pdp_list_apply_pword_method(t_pdp_list *l, - t_pdp_word_type type, t_pdp_pword_method pwm) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == type) pwm(&a->w); - } -} - -void pdp_tree_apply_word_method(t_pdp_list *l, - t_pdp_word_type type, t_pdp_word_method wm) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == a_list) pdp_tree_apply_word_method(a->w.w_list, type, wm); - else if (a->t == type) wm(a->w); - } -} -void pdp_tree_apply_pword_method(t_pdp_list *l, - t_pdp_word_type type, t_pdp_pword_method pwm) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == a_list) pdp_tree_apply_pword_method(a->w.w_list, type ,pwm); - else if (a->t == type) pwm(&a->w); - } -} - -static void _atom_packet_mark_unused(t_pdp_atom *a) -{ - if (a->t == a_packet){ - pdp_packet_mark_unused(a->w.w_packet); - a->t = a_undef; - a->w.w_int = 0; - } -} - -void pdp_tree_strip_packets (t_pdp_list *l) -{ - pdp_tree_apply(l, _atom_packet_mark_unused); -} - - -/* debug */ -static void _pdp_atomlist_fprint(FILE* f, t_pdp_atom *a) -{ - fprintf(f, "("); - while (a){ - switch(a->t){ - case a_symbol: fprintf(f, "%s",a->w.w_symbol->s_name); break; - case a_float: fprintf(f, "%f",a->w.w_float); break; - case a_int: fprintf(f, "%d",a->w.w_int); break; - case a_packet: fprintf(f, "#<pdp %d %s>",a->w.w_packet, - pdp_packet_get_description(a->w.w_packet)->s_name); break; - case a_pointer: fprintf(f, "#<0x%08x>",(unsigned int)a->w.w_pointer); break; - case a_list: _pdp_atomlist_fprint(f, a->w.w_list->first); break; - case a_undef: fprintf(f, "undef"); break; - - default: fprintf(f, "unknown"); break; - } - a = a->next; - if (a) fprintf(f, " "); - } - fprintf(f, ")"); -} - -void _pdp_list_fprint(FILE* f, t_pdp_list *l) -{ - _pdp_atomlist_fprint(f, l->first); - fprintf(f, "\n"); -} - -void pdp_list_print(t_pdp_list *l) -{ - _pdp_list_fprint(stderr, l); -} - - -/* public list operations */ - - -/* add a word to the start of the list */ -void pdp_list_add(t_pdp_list *l, t_pdp_word_type t, t_pdp_word w) -{ - t_pdp_atom *new_a = PDP_ATOM_ALLOC(); - l->elements++; - new_a->next = l->first; - new_a->w = w; - new_a->t = t; - l->first = new_a; - if (!l->last) l->last = new_a; -} - - -/* add a word to the end of the list */ -void pdp_list_add_back(t_pdp_list *l, t_pdp_word_type t, t_pdp_word w) -{ - t_pdp_atom *new_a = PDP_ATOM_ALLOC(); - l->elements++; - new_a->next = 0; - new_a->w = w; - new_a->t = t; - if (l->last){ - l->last->next = new_a; - } - else{ - l->first = new_a; - } - l->last = new_a; -} - -/* get list size */ -int pdp_list_size(t_pdp_list *l) -{ - return l->elements; -} - - - - -/* pop: return first item and remove */ -t_pdp_word pdp_list_pop(t_pdp_list *l) -{ - t_pdp_atom *a = l->first; - t_pdp_word w; - - w = a->w; - l->first = a->next; - PDP_ATOM_DEALLOC(a); - l->elements--; - if (!l->first) l->last = 0; - - return w; -} - - -/* return element at index */ -t_pdp_word pdp_list_index(t_pdp_list *l, int index) -{ - t_pdp_atom *a; - for (a = l->first; index--; a = a->next); - return a->w; -} - - - - - -/* remove an element from a list */ -void pdp_list_remove(t_pdp_list *l, t_pdp_word_type t, t_pdp_word w) -{ - t_pdp_atom head; - t_pdp_atom *a; - t_pdp_atom *kill_a; - head.next = l->first; - - for(a = &head; a->next; a = a->next){ - if (a->next->w.w_int == w.w_int && a->next->t == t){ - kill_a = a->next; // element to be killed - a->next = a->next->next; // remove link - PDP_ATOM_DEALLOC(kill_a); - l->elements--; - l->first = head.next; // restore the start pointer - if (l->last == kill_a) { // restore the end pointer - l->last = (a != &head) ? a : 0; - } - - break; - } - } - -} - - - - - -/* copy a list */ -t_pdp_list* pdp_tree_copy_reverse(t_pdp_list *list) -{ - t_pdp_list *newlist = pdp_list_new(0); - t_pdp_atom *a; - for (a = list->first; a; a = a->next) - if (a->t == a_list){ - pdp_list_add(newlist, a->t, - (t_pdp_word)pdp_tree_copy_reverse(a->w.w_list)); - } - else{ - pdp_list_add(newlist, a->t, a->w); - } - return newlist; -} -t_pdp_list* pdp_list_copy_reverse(t_pdp_list *list) -{ - t_pdp_list *newlist = pdp_list_new(0); - t_pdp_atom *a; - for (a = list->first; a; a = a->next) - pdp_list_add(newlist, a->t, a->w); - return newlist; -} - -t_pdp_list* pdp_tree_copy(t_pdp_list *list) -{ - t_pdp_list *newlist = pdp_list_new(list->elements); - t_pdp_atom *a_src = list->first; - t_pdp_atom *a_dst = newlist->first; - - while(a_src){ - a_dst->t = a_src->t; - if (a_dst->t == a_list){ //recursively copy sublists (tree copy) - a_dst->w.w_list = pdp_tree_copy(a_src->w.w_list); - } - else{ - a_dst->w = a_src->w; - } - a_src = a_src->next; - a_dst = a_dst->next; - } - - return newlist; -} -t_pdp_list* pdp_list_copy(t_pdp_list *list) -{ - t_pdp_list *newlist = pdp_list_new(list->elements); - t_pdp_atom *a_src = list->first; - t_pdp_atom *a_dst = newlist->first; - - while(a_src){ - a_dst->t = a_src->t; - a_dst->w = a_src->w; - a_src = a_src->next; - a_dst = a_dst->next; - } - return newlist; -} - -void pdp_list_cat (t_pdp_list *l, t_pdp_list *tail) -{ - t_pdp_list *tmp = pdp_list_copy(tail); - l->elements += tmp->elements; - l->last->next = tmp->first; - l->last = tmp->last; - _pdp_list_dealloc(tmp); //delete the list stub - -} - - -/* check if a list contains an element */ -int pdp_list_contains(t_pdp_list *list, t_pdp_word_type t, t_pdp_word w) -{ - t_pdp_atom *a; - for(a = list->first; a; a=a->next){ - if (a->w.w_int == w.w_int && a->t == t) return 1; - } - return 0; -} - -/* add a thing to the start of the list if it's not in there already */ -void pdp_list_add_to_set(t_pdp_list *list, t_pdp_word_type t, t_pdp_word w) -{ - if (!pdp_list_contains(list, t, w)) - pdp_list_add(list, t, w); -} - - - diff --git a/system/kernel/pdp_mem.c b/system/kernel/pdp_mem.c deleted file mode 100644 index 33822ef..0000000 --- a/system/kernel/pdp_mem.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Pure Data Packet system file: memory allocation - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <stdlib.h> -#include "pdp_mem.h" -#include "pdp_debug.h" - - -/* malloc wrapper that calls garbage collector */ -void *pdp_alloc(int size) -{ - void *ptr = malloc(size); - - PDP_ASSERT(ptr); - - return ptr; - - //TODO: REPAIR THIS - //post ("malloc failed in a pdp module: running garbage collector."); - //pdp_pool_collect_garbage(); - //return malloc(size); -} - - -void pdp_dealloc(void *stuff) -{ - free (stuff); -} - - -/* fast atom allocation object - well, this is not too fast yet, but will be later - when it suports linux futexes or atomic operations */ - -//#include <pthread.h> - -/* private linked list struct */ -typedef struct _fastalloc -{ - struct _fastalloc * next; -} t_fastalloc; - - - - -static void _pdp_fastalloc_lock(t_pdp_fastalloc *x){pthread_mutex_lock(&x->mut);} -static void _pdp_fastalloc_unlock(t_pdp_fastalloc *x){pthread_mutex_unlock(&x->mut);} - -static void _pdp_fastalloc_refill_freelist(t_pdp_fastalloc *x) -{ - t_fastalloc *atom; - unsigned int i; - - PDP_ASSERT(x->freelist == 0); - - /* get a new block - there is no means of freeing the data afterwards, - this is a fast implementation with the tradeoff of data - fragmentation "memory leaks".. */ - - x->freelist = pdp_alloc(x->block_elements * x->atom_size); - - /* link all atoms together */ - atom = x->freelist; - for (i=0; i<x->block_elements-1; i++){ - atom->next = (t_fastalloc *)(((char *)atom) + x->atom_size); - atom = atom->next; - } - atom->next = 0; - -} - -void *pdp_fastalloc_new_atom(t_pdp_fastalloc *x) -{ - t_fastalloc *atom; - - _pdp_fastalloc_lock(x); - - /* get an atom from the freelist - or refill it and try again */ - while (!(atom = x->freelist)){ - _pdp_fastalloc_refill_freelist(x); - } - - /* delete the element from the freelist */ - x->freelist = x->freelist->next; - atom->next = 0; - - _pdp_fastalloc_unlock(x); - - return (void *)atom; - -} -void pdp_fastalloc_save_atom(t_pdp_fastalloc *x, void *atom) -{ - _pdp_fastalloc_lock(x); - ((t_fastalloc *)atom)->next = x->freelist; - x->freelist = (t_fastalloc *)atom; - _pdp_fastalloc_unlock(x); -} - -t_pdp_fastalloc *pdp_fastalloc_new(unsigned int size) -{ - t_pdp_fastalloc *x = pdp_alloc(sizeof(*x)); - if (size < sizeof(t_fastalloc)) size = sizeof(t_fastalloc); - x->freelist = 0; - x->atom_size = size; - x->block_elements = PDP_FASTALLOC_BLOCK_ELEMENTS; - pthread_mutex_init(&x->mut, NULL); - return x; -} - diff --git a/system/kernel/pdp_packet.c b/system/kernel/pdp_packet.c deleted file mode 100644 index a811381..0000000 --- a/system/kernel/pdp_packet.c +++ /dev/null @@ -1,957 +0,0 @@ -/* - * Pure Data Packet system implementation: Packet Manager - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -#include "pdp.h" -#include <stdio.h> -#include <pthread.h> -#include <unistd.h> -#include <string.h> - - -/* TODO: - implement an indexing system to the packet pool (array) to speed up searches. - -> a list of lists of recycled packes, arranged by packet type. - -> a list of unused slots -*/ - - - -#define D if (0) - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - - -/* pdp specific constants */ -#define PDP_ALIGN 8 - -/* this needs to be able to grow dynamically, think about it later */ -/* for ordinary work, this is enough and can help finding memory leaks */ - -#define PDP_INITIAL_POOL_SIZE 1 -#define PDP_PACKET_MAX_MEM_USAGE -1 - -/* the pool */ -static unsigned int pdp_packet_mem_usage; -static unsigned int pdp_packet_max_mem_usage; -static int pdp_pool_size; -static t_pdp** pdp_pool; - -/* this is for detecting memory leaks */ -static int pdp_packet_count; - -/* some global vars */ -static t_symbol* pdp_sym_register_rw; -static t_symbol* pdp_sym_register_ro; -static t_symbol* pdp_sym_process; - -/* mutex */ -static pthread_mutex_t pdp_pool_mutex; - -/* the list of classes */ -static t_pdp_list *class_list; - -/* debug */ -void -pdp_packet_print_debug(int packet) -{ - t_pdp *h = pdp_packet_header(packet); - post("debug info for packet %d", packet); - if (!h){ - post("invalid packet"); - } - else{ - post ("\ttype: %d", h->type); - post ("\tdesc: %s", h->desc ? h->desc->s_name : "unknown"); - post ("\tsize: %d", h->size); - post ("\tflags: %x", h->flags); - post ("\tusers: %d", h->users); - post ("\trefloc: %x", h->refloc); - post ("\tclass: %x", h->theclass); - } -} - - - -/* setup methods */ - -void -pdp_packet_setup(void) -{ - - pdp_pool_size = PDP_INITIAL_POOL_SIZE; - pdp_packet_count = 0; - pdp_packet_mem_usage = 0; - pdp_packet_max_mem_usage = PDP_PACKET_MAX_MEM_USAGE; - pdp_pool = (t_pdp **)malloc(PDP_INITIAL_POOL_SIZE * sizeof(t_pdp *)); - bzero(pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - pdp_sym_register_rw = gensym("register_rw"); - pdp_sym_register_ro = gensym("register_ro"); - pdp_sym_process = gensym("process"); - pdp_packet_count = 0; - class_list = pdp_list_new(0); - - pthread_mutex_init(&pdp_pool_mutex, NULL); -} - -/* class methods */ -t_pdp_class *pdp_class_new(t_pdp_symbol *type, t_pdp_factory_method create){ - t_pdp_class *c = (t_pdp_class *)pdp_alloc(sizeof(t_pdp_class)); - memset(c, 0, sizeof(t_pdp_class)); - c->create = create; - c->type = type; // set type - //c->attributes = pdp_list_new(0); // create an empty attribute list - pdp_list_add(class_list, a_pointer, (t_pdp_word)((void *)c)); - //post("added class %s %x", c->type->s_name, c->create); - - return c; -} - -#if 0 -void pdp_class_addmethod(t_pdp_class *c, t_pdp_symbol *name, t_pdp_attribute_method method, - t_pdp_list *in_spec, t_pdp_list *out_spec) -{ - t_pdp_attribute *attr = (t_pdp_attribute *)pdp_alloc(sizeof(t_pdp_attribute)); - attr->name = name; - attr->method = method; - attr->in_spec = in_spec; - attr->out_spec = out_spec; - pdp_list_add_pointer(c->attributes, attr); - -} -#endif - -/* the packet factory */ -int pdp_factory_newpacket(t_pdp_symbol *type) -{ - t_pdp_class *c; - t_pdp_atom *a = class_list->first; - while(a){ - c = (t_pdp_class *)(a->w.w_pointer); - if (c->type && pdp_type_description_match(type, c->type)){ - //post("method %x, type %s", c->create, type->s_name); - return (c->create) ? (*c->create)(type) : -1; - } - a = a->next; - } - return -1; -} - -#if 0 -/* generic methods. actually a forth word operation on a stack. - first item on stack must be a packet and it's type will - determine the place to look for the operator */ -int pdp_packet_op(t_pdp_symbol *operation, struct _pdp_list *stack) -{ - int packet = stack->first->w.w_packet; - t_pdp *h = pdp_packet_header(packet); - t_pdp_atom *i; - t_pdp_attribute *attr; - - if (!(h && h->theclass)) goto exit; - - PDP_POINTER_IN(h->theclass->attributes, i, attr){ - //post("attribute:%s", attr->name->s_name); - if (attr->name == operation){ - - /* FOUND -> exec (check arguments first ???) */ - return attr->method (stack); - } - - } - exit: - // method not found - post ("WARNING: pdp_packet_op: packet %d from class %s has no operation %s", - packet, (h && h->theclass) ? h->theclass->type->s_name : "UNKNOWN", operation->s_name); - return 0; -} - -#endif - -static void -_pdp_pool_expand(void){ - int i; - - /* double the size */ - int new_pool_size = pdp_pool_size << 1; - t_pdp **new_pool = (t_pdp **)malloc(new_pool_size * sizeof(t_pdp *)); - bzero(new_pool, new_pool_size * sizeof(t_pdp *)); - memcpy(new_pool, pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - free(pdp_pool); - pdp_pool = new_pool; - pdp_pool_size = new_pool_size; - - D post("DEBUG: _pdp_pool_expand: resized pool to contain %d packets", pdp_pool_size); -} - - - - -/* private _pdp_packet methods */ - -/* packets can only be created and destroyed using these 2 methods */ -/* it updates the mem usage and total packet count */ - -static void -_pdp_packet_dealloc(t_pdp *p) -{ - unsigned int size = p->size; - if (p->theclass && p->theclass->cleanup) - (*p->theclass->cleanup)(p); - - free (p); - pdp_packet_mem_usage -= size; - pdp_packet_count--; - D post("DEBUG: _pdp_packet_new_dealloc: freed packet. pool contains %d packets", pdp_packet_count); -} - -static t_pdp* -_pdp_packet_alloc(unsigned int datatype, unsigned int datasize) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - unsigned int align; - t_pdp *p = 0; - - /* check if there is a memory usage limit */ - if (pdp_packet_max_mem_usage){ - /* if it would exceed the limit, fail */ - if (pdp_packet_mem_usage + totalsize > pdp_packet_max_mem_usage){ - D post("DEBUG: _pdp_packet_new_alloc: memory usage limit exceeded"); - return 0; - } - } - p = (t_pdp *)malloc(totalsize); - if (p){ - align = ((unsigned int)p) & (PDP_ALIGN - 1); - if (align) post("WARNING: _pdp_packet_alloc: data misaligned by %x", align); - memset(p, 0, PDP_HEADER_SIZE); //initialize header to 0 - p->type = datatype; - p->size = totalsize; - p->users = 1; - pdp_packet_mem_usage += totalsize; - pdp_packet_count++; - D post("DEBUG: _pdp_packet_new_alloc: allocated new packet. pool contains %d packets, using %d bytes", - pdp_packet_count, pdp_packet_mem_usage); - } - - return p; -} - - -void -pdp_packet_destroy(void) -{ - int i = 0; - /* dealloc all the data in object stack */ - post("DEBUG: pdp_packet_destroy: clearing object pool."); - while ((i < pdp_pool_size) && (pdp_pool[i])) _pdp_packet_dealloc(pdp_pool[i++]); -} - - - -/* try to find a packet based on main type and datasize */ -static int -_pdp_packet_reuse_type_size(unsigned int datatype, unsigned int datasize) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - int i = 0; - int return_packet = -1; - t_pdp* p; - - for (i=0; i < pdp_pool_size; i++){ - p = pdp_pool[i]; - /* check if we can reuse this one if it is already allocated */ - if (p) { - /* search for unused packets of equal size & type */ - if ((p->users == 0) && (p->size == totalsize) && (p->type == datatype)){ - D post("DEBUG: _pdp_packet_reuse_type_size: can reuse %d", i); - - /* if possible, a packet will be reused and reinitialized - i haven't found a use for this, so it's only used for discriminating - between pure and not-so-pure packets */ - if (p->theclass && p->theclass->reinit){ - (*p->theclass->reinit)(p); - } - /* if no re-init method is found, the header will be reset to all 0 - this ensures the header is in a predictable state */ - else { - memset(p, 0, PDP_HEADER_SIZE); - p->type = datatype; - p->size = totalsize; - } - - p->users = 1; - return_packet = i; - goto exit; - } - else{ - D post("DEBUG _pdp_packet_reuse_type_size: can't reuse %d, (%d users)", i, p->users); - } - } - } - - D post("DEBUG: _pdp_packet_reuse_type_size: no reusable packet found"); - - exit: - return return_packet; -} - - -/* create a new packet in an empty slot. - if this fails, the garbage collector needs to be called */ -static int -_pdp_packet_create_in_empty_slot(unsigned int datatype, unsigned int datasize /*without header*/) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - int i = 0; - int return_packet = -1; - int out_of_mem = 0; - t_pdp* p; - - - /* no reusable packets found, try to find an empty slot */ - for (i=0; i < pdp_pool_size; i++){ - p = pdp_pool[i]; - if (!p) { - p = _pdp_packet_alloc(datatype, datasize); - - if (!p) { - D post("DEBUG: _pdp_packet_create_in_empty_slot: out of memory (malloc returned NULL)"); - return_packet = -1; - goto exit; - } - - pdp_pool[i] = p; - return_packet = i; - goto exit; - } - } - - /* if we got here the pool is full: resize the pool and try again */ - _pdp_pool_expand(); - return_packet = _pdp_packet_create_in_empty_slot(datatype, datasize); - - exit: - return return_packet; - -} - -/* find an unused packet, free it and create a new packet. - if this fails, something is seriously wrong */ -static int -_pdp_packet_create_in_unused_slot(unsigned int datatype, unsigned int datasize /*without header*/) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - int i = 0; - int return_packet = -1; - int out_of_mem = 0; - t_pdp* p; - - D post("DEBUG: _pdp_packet_create_in_unused_slot: collecting garbage"); - - /* search backwards */ - for (i=pdp_pool_size-1; i >= 0; i--){ - p = pdp_pool[i]; - if (p){ - if (p->users == 0){ - _pdp_packet_dealloc(p); - p = _pdp_packet_alloc(datatype, datasize); - pdp_pool[i] = p; - - /* alloc succeeded, return */ - if (p) { - post("DEBUG _pdp_packet_create_in_unused_slot: garbage collect succesful"); - return_packet = i; - goto exit; - } - - /* alloc failed, continue collecting garbage */ - D post("DEBUG _pdp_packet_create_in_unused_slot: freed one packet, still out of memory (malloc returned NULL)"); - out_of_mem = 1; - - } - } - } - - /* if we got here, we ran out of memory */ - D post("DEBUG: _pdp_packet_create_in_unused_slot: out of memory after collecting garbage"); - return_packet = -1; - -exit: - return return_packet; -} - -/* warning: for "not so pure" packets, this method will only return an initialized - packet if it can reuse a privious one. that is, if it finds a reinit method - in the packet. use the pdp_packet_new_<type> constructor if possible */ - -static int -_pdp_packet_brandnew(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int return_packet = -1; - - /* try to create a new packet in an empty slot */ - return_packet = _pdp_packet_create_in_empty_slot(datatype, datasize); - if (return_packet != -1) goto exit; - - /* if we still don't have a packet, we need to call the garbage collector until we can allocate */ - return_packet = _pdp_packet_create_in_unused_slot(datatype, datasize); - - exit: - return return_packet; -} - - -static int -_pdp_packet_new(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int return_packet = -1; - - /* try to reuse a packet based on main type and datasize */ - return_packet = _pdp_packet_reuse_type_size(datatype, datasize); - if (return_packet != -1) goto exit; - - /* create a brandnew packet */ - return_packet = _pdp_packet_brandnew(datatype, datasize); - if (return_packet != -1) goto exit; - - post("WARNING: maximum packet memory usage limit (%d bytes) reached after garbage collect.", pdp_packet_max_mem_usage); - post("WARNING: increase memory limit or decrease packet usage (i.e. pdp_loop, pdp_delay)."); - post("WARNING: pool contains %d packets, using %d bytes.", pdp_packet_count, pdp_packet_mem_usage); - - exit: - return return_packet; - -} - - - -/* public pool operations: have to be thread safe so each entry point - locks the mutex */ - -/* reuse an old packet based on high level description */ -int -pdp_packet_reuse(t_pdp_symbol *description) -{ - int i; - int return_packet = -1; - t_pdp *p; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - for (i=0; i < pdp_pool_size; i++){ - p = pdp_pool[i]; - /* check if we can reuse this one if it is already allocated */ - if ((p) && (p->users == 0) && (p->desc == description)){ - /* mark it as used */ - p->users = 1; - return_packet = i; - goto gotit; - } - } - - gotit: - /* LOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - - return return_packet; - - -} - -/* create a new packet, or reuse an old one based on main type and size */ -int -pdp_packet_new(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int packet; - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - packet = _pdp_packet_new(datatype, datasize); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - return packet; -} - - -/* create a brand new packet, don't reuse an old one */ -int -pdp_packet_brandnew(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int packet; - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - packet = _pdp_packet_brandnew(datatype, datasize); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - return packet; -} - - -/* this returns a copy of a packet for read only access. */ -int -pdp_packet_copy_ro(int handle) -{ - int out_handle = -1; - t_pdp* p; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - if ((handle >= 0) - && (handle < pdp_pool_size) - && (p = pdp_pool[handle])){ - - /* it is an error to copy a packet without an owner */ - if (!p->users){ - post("pdp_packet_copy_ro: ERROR: request to copy packet %d which has 0 users", handle); - out_handle = -1; - } - - /* if it's a passing packet, reset the reference location - and turn it into a normal packet */ - else if (p->refloc){ - *p->refloc = -1; - p->refloc = 0; - out_handle = handle; - } - /* if it's a normal packet, increase the number of users */ - else { - p->users++; - out_handle = handle; - } - } - else out_handle = -1; - - //post("pdp_copy_ro: outhandle:%d", out_handle); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - - return out_handle; -} - -/* copy a packet. if the packet is marked passing, it will be aquired. - otherwize a new packet will be created with a copy of the contents. */ - -int -pdp_packet_copy_rw(int handle) -{ - int out_handle = -1; - t_pdp* p; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - if ((handle >= 0) - && (handle < pdp_pool_size) - && (p = pdp_pool[handle])){ - /* if there are other users, copy the object otherwize return the same handle */ - - /* it is an error to copy a packet without an owner */ - if (!p->users){ - post("pdp_packet_copy_rw: ERROR: request to copy packet %d which has 0 users", handle); - out_handle = -1; - } - - /* if it is a passing packet, remove the owner's reference to it */ - else if (p->refloc){ - *p->refloc = -1; - p->refloc = 0; - out_handle = handle; - } - - /* check if packet supports copy (for fanout) */ - else if(p->flags & PDP_FLAG_DONOTCOPY) out_handle = -1; - - - /* copy the packet, since it already has 1 or more users */ - else{ - int new_handle = _pdp_packet_new(p->type, p->size - PDP_HEADER_SIZE); - t_pdp* new_p = pdp_packet_header(new_handle); - - /* check if valid */ - if (!new_p) out_handle = -1; - - else { - /* if a copy constructor is found, it will be called */ - if (p->theclass && p->theclass->copy){ - (*p->theclass->copy)(new_p, p); - } - /* if not, the entire packet will be copied, assuming a pure data packet */ - else { - memcpy(new_p, p, p->size); - } - new_p->users = 1; - out_handle = new_handle; - } - } - - //post("pdp_copy_rw: inhandle:%d outhandle:%d", handle, out_handle); - - } - else out_handle = -1; - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - return out_handle; -} - -/* create a new packet, copying the header data of another - packet, without copying the data */ -int -pdp_packet_clone_rw(int handle) -{ - int out_handle; - t_pdp* p; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - if ((handle >= 0) - && (handle < pdp_pool_size) - && (p = pdp_pool[handle])){ - - /* clone the packet header, don't copy the data */ - int new_handle = _pdp_packet_new(p->type, p->size - PDP_HEADER_SIZE); - t_pdp* new_p = pdp_packet_header(new_handle); - - /* if a clone initializer is found, it will be called */ - if (p->theclass && p->theclass->clone){ - (*p->theclass->clone)(new_p, p); - } - /* if not, just the header will be copied, assuming a pure data packet */ - else { - memcpy(new_p, p, PDP_HEADER_SIZE); - } - new_p->users = 1; /* the new packet has 1 user */ - new_p->refloc = 0; /* it is not a passing packet, even if the template was */ - out_handle = new_handle; - } - - else out_handle = -1; - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - - return out_handle; -} - -void -_pdp_packet_mark_unused_nolock(int handle) -{ - t_pdp* p; - - if ((handle >= 0) && (handle < pdp_pool_size)){ - if (p = pdp_pool[handle]) { - /* mark_unused on a passing packet has no effect - this is to support automatic conversion for passing packets - so in order to delete a passing packet, it should be marked normal first */ - if (p->refloc){ - post("DEBUG: pdp_mark_unused called on a passing packet. ignored."); - return; - } - - /* decrease the refcount */ - if (p->users) { - p->users--; - //post("pdp_mark_unused: handle %d, users left %d", handle, p->users); - } - else { - post("pdp_mark_unused: ERROR: handle %d has zero users (duplicate pdp_mark_unused ?)", handle); - } - } - else { - post("pdp_mark_unused: ERROR: invalid handle %d: no associated object", handle); - } - } - - else { - /* -1 is the only invalid handle that doesn't trigger a warning */ - if (handle != -1) post("pdp_mark_unused: WARNING: invalid handle %d: out of bound", handle); - } - -} - -/* mark a packet as unused, decreasing the reference count. - if the reference count reaches zero, the packet is ready to be recycled - by a new packet allocation. it is illegal to reference a packet with - reference count == zero. if the reference count is not == 1, only readonly - access is permitted. */ - -void -pdp_packet_mark_unused(int handle) -{ - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - _pdp_packet_mark_unused_nolock(handle); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); -} - -void -pdp_packet_mark_unused_atomic(int *handle) -{ - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - _pdp_packet_mark_unused_nolock(*handle); - *handle = -1; - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); -} - -/* delete a packet. this is more than mark_unused: - it actually removes any reference. can be used for - some packet types that have "expensive" resources. - usually this is up to the garbage collector to call. */ - -void -pdp_packet_delete(int handle) -{ - t_pdp *header = pdp_packet_header(handle); - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - - /* check if it's a valid handle */ - if ((handle >= 0) && (handle < pdp_pool_size) && pdp_pool[handle]){ - - /* mark it unused */ - _pdp_packet_mark_unused_nolock(handle); - - /* if no users, dealloc */ - if (!header->users){ - _pdp_packet_dealloc(header); - pdp_pool[handle] = NULL; - } - - /* print a warning if failed */ - else{ - post("WARNING: pdp_packet_delete: packet %d was not deleted. %d users remaining", - handle, header->users); - } - } - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - -} - - -/* this turns any packet into a normal (non-passing) packet */ - -void -pdp_packet_unmark_passing(int packet) -{ - t_pdp* header = pdp_packet_header(packet); - if (!header) return; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - header->refloc = 0; - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - -} - - -/* this marks a packet as passing. this means it changes - owner on first copy_ro or copy_rw. the previous owner is - notified by setting the handler to -1. */ - -void -pdp_packet_mark_passing(int *phandle) -{ - t_pdp* header = pdp_packet_header(*phandle); - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - if (header){ - if (header->refloc){ - post("pdp_packet_mark_passing: ERROR: duplicate mark_passing on packet %d", *phandle); - } - else if (1 != header->users){ - post("pdp_packet_mark_passing: ERROR: packet %d is not exclusively owned by caller, it has %d users", *phandle, header->users); - } - else { - header->refloc = phandle; - } - } - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - -} - - -/* public data access methods */ - -t_pdp* -pdp_packet_header(int handle) -{ - if ((handle >= 0) && (handle < pdp_pool_size)) return pdp_pool[handle]; - else return 0; -} - -void* -pdp_packet_subheader(int handle) -{ - t_pdp* header = pdp_packet_header(handle); - if (!header) return 0; - return (void *)(&header->info.raw); -} - -void* -pdp_packet_data(int handle) -{ - t_pdp *h; - if ((handle >= 0) && (handle < pdp_pool_size)) - { - h = pdp_pool[handle]; - if (!h) return 0; - return (char *)(h) + PDP_HEADER_SIZE; - } - else return 0; -} - - -/* OBSOLETE: use packet description */ -/* check if two packets are allocated and of the same type */ -bool pdp_packet_compat(int packet0, int packet1) -{ - - t_pdp *header0 = pdp_packet_header(packet0); - t_pdp *header1 = pdp_packet_header(packet1); - - if (!(header1)){ - //post("pdp_type_compat: invalid header packet1"); - return 0; - } - if (!(header0)){ - //post("pdp_type_compat: invalid header packet 0"); - return 0; - } - if (header0->type != header1->type){ - //post("pdp_type_compat: types do not match"); - return 0; - } - - return 1; -} - -int pdp_packet_writable(int packet) /* returns true if packet is writable */ -{ - t_pdp *h = pdp_packet_header(packet); - if (!h) return 0; - return (h->users == 1); -} - -void pdp_packet_replace_with_writable(int *packet) /* replaces a packet with a writable copy */ -{ - int new_p; - if (!pdp_packet_writable(*packet)){ - new_p = pdp_packet_copy_rw(*packet); - pdp_packet_mark_unused(*packet); - *packet = new_p; - } - -} - -/* pool stuff */ - -int -pdp_pool_collect_garbage(void) -{ - t_pdp *p; - int i; - int nbpackets = pdp_packet_count; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - for (i=0; i < pdp_pool_size; i++){ - p = pdp_pool[i]; - if(p && !p->users) { - _pdp_packet_dealloc(p); - pdp_pool[i] = 0; - } - } - nbpackets -= pdp_packet_count; - //post("pdp_pool_collect_garbage: deleted %d unused packets", nbpackets); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - - return nbpackets; -} - -void -pdp_pool_set_max_mem_usage(int max) -{ - if (max < 0) max = 0; - pdp_packet_max_mem_usage = max; - -} - - - - - - -/* malloc wrapper that calls garbage collector */ -void *pdp_alloc(int size) -{ - void *ptr = malloc(size); - - //post ("malloc called for %d bytes", size); - - if (ptr) return ptr; - - post ("malloc failed in a pdp module: running garbage collector."); - - pdp_pool_collect_garbage(); - return malloc(size); -} - - -void pdp_dealloc(void *stuff) -{ - free (stuff); -} - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_packet2.c b/system/kernel/pdp_packet2.c deleted file mode 100644 index 3717a77..0000000 --- a/system/kernel/pdp_packet2.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Pure Data Packet system implementation: Packet Manager - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - - -#include <stdio.h> -#include <pthread.h> -#include <unistd.h> -#include <string.h> -#include "pdp_post.h" -#include "pdp_packet.h" -#include "pdp_mem.h" -#include "pdp_list.h" -#include "pdp_type.h" -#include "pdp_debug.h" - - -/* packet implementation. contains class and packet (instance) handling - - some notes on packet operations. - copy ro/rw and unregister are relatively straightforward - packet creation can be done in 2 ways in this interface: - create + reuse - however, these methods should only be called by specific factory - methods, so the user should only create packets using pdp_factory_newpacket - - reuse or create is thus the responsability of the factory methods for - each packet type (class) implementation - - -*/ - - -/* NOTE: - the packet pool methods are called within the pool locks. this probably - needs to change, because it will cause deadlocks for container packets (fobs) */ - - -/* new implementation: probably just a minor adjustment: add the reuse fifo attached - to type desc symbol name - need to check and possibly eliminate hacks for non-pure packets - - pdp_packet_new: - LOCK - 1. check reuse fifo - 2. empty -> create packet+return (search array) - 3. element -> check if type is correct, yes->pop+return, no->goto 1. - UNLOCK - 4. wakeup - - pdp_packet_mark_unused - - 1. check refcount. if > 1 dec + exit - 2. if 1 put packet to sleep - 3. dec refcount - 4. add to reuse fifo (no fifo -> create) - - pdp_packet_delete: analogous to mark_unused - pdp_packet_copy_ro/rw: analogous to new - -*/ - - -/* the pool */ -#define PDP_INITIAL_POOL_SIZE 64 -static int pdp_pool_size; -static t_pdp** pdp_pool; - -/* mutex: protects the pool and reuse lists attached to symbols */ -static pthread_mutex_t pdp_pool_mutex; -#define LOCK pthread_mutex_lock (&pdp_pool_mutex) -#define UNLOCK pthread_mutex_unlock (&pdp_pool_mutex) - -/* the list of classes */ -static t_pdp_list *class_list; - -/* debug */ -void -pdp_packet_print_debug(int packet) -{ - t_pdp *h = pdp_packet_header(packet); - pdp_post("debug info for packet %d", packet); - if (!h){ - pdp_post("invalid packet"); - } - else{ - pdp_post ("\ttype: %d", h->type); - pdp_post ("\tdesc: %s", h->desc ? h->desc->s_name : "unknown"); - pdp_post ("\tsize: %d", h->size); - pdp_post ("\tflags: %x", h->flags); - pdp_post ("\tusers: %d", h->users); - pdp_post ("\tclass: %x", h->theclass); - } -} - - - -/* setup methods */ - -void -pdp_packet_setup(void) -{ - - pdp_pool_size = PDP_INITIAL_POOL_SIZE; - pdp_pool = (t_pdp **)pdp_alloc(PDP_INITIAL_POOL_SIZE * sizeof(t_pdp *)); - bzero(pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - class_list = pdp_list_new(0); - pthread_mutex_init(&pdp_pool_mutex, NULL); -} - -/* class methods */ -t_pdp_class *pdp_class_new(t_pdp_symbol *type, t_pdp_factory_method create){ - t_pdp_class *c = (t_pdp_class *)pdp_alloc(sizeof(t_pdp_class)); - memset(c, 0, sizeof(t_pdp_class)); - c->create = create; - c->type = type; // set type - pdp_list_add(class_list, a_pointer, (t_pdp_word)((void *)c)); - return c; -} - -/* the packet factory */ -int pdp_factory_newpacket(t_pdp_symbol *type) -{ - int p; - t_pdp_class *c; - t_pdp_atom *a = class_list->first; - - /* try to reuse first - THINK: should this be the responsability of the type specific constructors, - or should a packet allways be reusable (solution: depends on what the cleanup method returns??) - */ - p = pdp_packet_reuse(type); - if (-1 != p) return p; - - - /* call class constructor */ - while(a){ - c = (t_pdp_class *)(a->w.w_pointer); - if (c->type && pdp_type_description_match(type, c->type)){ - //pdp_post("method %x, type %s", c->create, type->s_name); - return (c->create) ? (*c->create)(type) : -1; - } - a = a->next; - } - return -1; -} - -static void -_pdp_pool_expand_nolock(void){ - int i; - - /* double the size */ - int new_pool_size = pdp_pool_size << 1; - t_pdp **new_pool = (t_pdp **)pdp_alloc(new_pool_size * sizeof(t_pdp *)); - bzero(new_pool, new_pool_size * sizeof(t_pdp *)); - memcpy(new_pool, pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - pdp_dealloc(pdp_pool); - pdp_pool = new_pool; - pdp_pool_size = new_pool_size; -} - - - - -/* private _pdp_packet methods */ - -/* packets can only be created and destroyed using these 2 methods */ -/* it updates the mem usage and total packet count */ - -static void -_pdp_packet_dealloc_nolock(t_pdp *p) -{ - /* free memory */ - pdp_dealloc (p); -} - -static t_pdp* -_pdp_packet_alloc_nolock(unsigned int datatype, unsigned int datasize) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - t_pdp *p = (t_pdp *)pdp_alloc(totalsize); - if (p){ - memset(p, 0, PDP_HEADER_SIZE); //initialize header to 0 - p->type = datatype; - p->size = totalsize; - p->users = 1; - } - return p; -} - - -/* create a new packet and expand pool if necessary */ -static int -_pdp_packet_create_nolock(unsigned int datatype, unsigned int datasize) -{ - int p = 0; - while(1){ - for (; p < pdp_pool_size; p++){ - if (!pdp_pool[p]){ - /* found slot to store packet*/ - t_pdp *header = _pdp_packet_alloc_nolock(datatype, datasize); - if (!header) return -1; // error allocating packet - pdp_pool[p] = header; - return p; - } - } - /* no slot found, expand pool */ - _pdp_pool_expand_nolock(); - } -} - - -void -pdp_packet_destroy(void) -{ - int i = 0; - /* dealloc all the data in object stack */ - pdp_post("DEBUG: pdp_packet_destroy: clearing object pool."); - while ((i < pdp_pool_size) && (pdp_pool[i])) _pdp_packet_dealloc_nolock(pdp_pool[i++]); -} - - - - - - - - -/* public pool operations: have to be thread safe so each entry point - locks the mutex */ - - -/* create a new packet. - this should only be used by type specific factory methods, and only if the - reuse method fails, since it will always create a new packet */ -int -pdp_packet_create(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int packet; - LOCK; - packet = _pdp_packet_create_nolock(datatype, datasize); - UNLOCK; - return packet; -} - - -/* return a new packet. - it tries to reuse a packet based on - 1. matching data size - 2. abscence of destructor (which SHOULD mean there are no enclosed references) - - it obviously can't use the reuse fifo tagged to a symbolic type description - - ALWAYS USE pdp_packet_reuse BEFORE calling pdp_packet_new if possible - use both ONLY IN CONSTRUCTORS !!! - - use pdp_packet_factory to create packets as a "user" - - this is a summary of all internal packet creation mechanisms: - - -> pdp_packet_reuse, which uses symbolic type descriptions, and should work for all packet types - it returns an initialized container (meta = correct, data = garbage) - - -> pdp_packet_new, which only works for non-pure packets, and reuses packets based on data type - it returns a pure packet (meta + data = garbage) - - -> pdp_packet_create, like pdp_packet_new, only it always creates a new packet - - - -*/ - -int -pdp_packet_new(unsigned int datatype, unsigned int datasize) -{ - t_pdp *header; - int packet; - LOCK; - for (packet = 0; packet < pdp_pool_size; packet++){ - header = pdp_pool[packet]; - /* check data size */ - if (header - && header->users == 0 - && header->size == datasize + PDP_HEADER_SIZE - && !(header->theclass && header->theclass->cleanup)){ - - /* ok, got one. initialize */ - memset(header, 0, PDP_HEADER_SIZE); - header->users = 1; - header->type = datatype; - header->size = datasize + PDP_HEADER_SIZE; - - UNLOCK; //EXIT1 - return packet; - } - } - - /* no usable non-pure packet found, create a new one */ - - UNLOCK; //EXIT2 - return pdp_packet_create(datatype, datasize); - - - -} - - -/* internal method to add a packet to a packet type - description symbol's unused packet fifo */ -void -_pdp_packet_save_nolock(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - t_pdp_symbol *s; - PDP_ASSERT(header); - PDP_ASSERT(header->users == 0); - PDP_ASSERT(header->desc); - s = header->desc; - if (!s->s_reusefifo) s->s_reusefifo = pdp_list_new(0); - pdp_list_add(s->s_reusefifo, a_packet, (t_pdp_word)packet); -} - -/* this will revive a packet matching a certain type description - no wildcards are allowed */ -int -pdp_packet_reuse(t_pdp_symbol *type_description) -{ - int packet = -1; - t_pdp *header = 0; - t_pdp_list *l = 0; - LOCK; - if (!type_description || !(l = type_description->s_reusefifo)) goto exit; - while(l->elements){ - packet = pdp_list_pop(l).w_packet; - header = pdp_packet_header(packet); - - /* check if reuse fifo is consistent (packet unused + correct type) - packet could be deleted and replaced with another one, or - revived without the index updated (it's a "hint cache") */ - - if (header->users == 0){ - /* check if type matches */ - if (pdp_type_description_match(header->desc, type_description)){ - header->users++; // revive - goto exit; - } - /* if not, add the packet to the correct reuse fifo */ - else{ - _pdp_packet_save_nolock(packet); - } - } - - /* remove dangling refs */ - header = 0; - packet = -1; - } - - exit: - UNLOCK; - if (header && header->theclass && header->theclass->wakeup){ - header->theclass->wakeup(header); // revive if necessary - } - return packet; -} - -/* find all unused packets in pool, marked as used (to protect from other reapers) - and return them as a list. non-pure packets are not revived */ - - - - - -/* this returns a copy of a packet for read only access. - (increases refcount of the packet -> packet will become readonly if it was - writable, i.e. had rc=1 */ - -int -pdp_packet_copy_ro(int handle) -{ - t_pdp* header; - - if (header = pdp_packet_header(handle)){ - PDP_ASSERT(header->users); // consistency check - LOCK; - header->users++; // increment reference count - UNLOCK; - } - else handle = -1; - return handle; -} - -/* clone a packet: create a new packet with the same - type as the source packet */ - -int -pdp_packet_clone_rw(int handle) -{ - t_pdp* header; - int new_handle = -1; - - - if (header = pdp_packet_header(handle)){ - /* consistency checks */ - PDP_ASSERT(header->users); - PDP_ASSERT(header->desc); - - /* first try to reuse old packet */ - new_handle = pdp_packet_reuse(header->desc); - - /* if this failed, create a new one using the central packet factory method */ - if (-1 == new_handle) new_handle = pdp_factory_newpacket(header->desc); - } - - return new_handle; -} - -/* return a copy of a packet (clone + copy data) */ -int -pdp_packet_copy_rw(int handle) -{ - t_pdp *header, *new_header; - int new_handle = -1; - - if (!(header = pdp_packet_header(handle))) return -1; - - /* check if we are allowed to copy */ - if (header->flags & PDP_FLAG_DONOTCOPY) return -1; - - /* get target packet */ - new_handle = pdp_packet_clone_rw(handle); - if (-1 == new_handle) return -1; - new_header = pdp_packet_header(new_handle); - - /* if there is a copy method, use that one */ - if (header->theclass && header->theclass->copy){ - header->theclass->copy(header, new_header); - } - - /* otherwize copy the data verbatim */ - else { - memcpy(pdp_packet_data(new_handle), - pdp_packet_data(handle), - pdp_packet_data_size(handle)); - } - - return new_handle; - -} - - -/* decrement refcount */ -void pdp_packet_mark_unused(int handle) -{ - t_pdp *header; - if (!(header = pdp_packet_header(handle))) return; - - PDP_ASSERT(header->users); // consistency check - - LOCK; - - /* just decrement refcount */ - if (header->users > 1){ - header->users--; - } - - /* put packet to sleep if refcount 1->0 */ - else { - if (header->theclass && header->theclass->sleep){ - /* call sleep method (if any) outside of lock - while the packet is still alive, so it won't be - acclaimed by another thread */ - UNLOCK; - header->theclass->sleep(header); - LOCK; - } - /* clear refcount & save in fifo for later use */ - header->users = 0; - if (header->desc) // sleep could have destructed packet.. - _pdp_packet_save_nolock(handle); - } - - UNLOCK; -} - - - -/* delete a packet. rc needs to be == 1 */ -void pdp_packet_delete(int handle) -{ - t_pdp *header; - header = pdp_packet_header(handle); - PDP_ASSERT(header); - PDP_ASSERT(header->users == 1); // consistency check - - LOCK; - - if (header->theclass && header->theclass->cleanup){ - /* call cleanup method (if any) outside of lock - while the packet is still alive, so it won't be - acclaimed by another thread */ - UNLOCK; - header->theclass->cleanup(header); - LOCK; - } - - /* delete the packet */ - pdp_pool[handle] = 0; - _pdp_packet_dealloc_nolock(header); - - - UNLOCK; -} - - - - - - - -/* public data access methods */ - -t_pdp* -pdp_packet_header(int handle) -{ - if ((handle >= 0) && (handle < pdp_pool_size)) return pdp_pool[handle]; - else return 0; -} - -void* -pdp_packet_subheader(int handle) -{ - t_pdp* header = pdp_packet_header(handle); - if (!header) return 0; - return (void *)(&header->info.raw); -} - -void* -pdp_packet_data(int handle) -{ - t_pdp *h; - if ((handle >= 0) && (handle < pdp_pool_size)) - { - h = pdp_pool[handle]; - if (!h) return 0; - return (char *)(h) + PDP_HEADER_SIZE; - } - else return 0; -} - -int -pdp_packet_data_size(int handle) -{ - t_pdp *h; - if ((handle >= 0) && (handle < pdp_pool_size)) - { - h = pdp_pool[handle]; - if (!h) return 0; - return h->size - PDP_HEADER_SIZE; - } - else return 0; -} - - - - -int pdp_packet_writable(int packet) /* returns true if packet is writable */ -{ - t_pdp *h = pdp_packet_header(packet); - if (!h) return 0; - return (h->users == 1); -} - -void pdp_packet_replace_with_writable(int *packet) /* replaces a packet with a writable copy */ -{ - int new_p; - if (!pdp_packet_writable(*packet)){ - new_p = pdp_packet_copy_rw(*packet); - pdp_packet_mark_unused(*packet); - *packet = new_p; - } - -} - -/* pool stuff */ - -int -pdp_pool_collect_garbage(void) -{ - pdp_post("ERROR: garbage collector not implemented"); - return 0; -} - -void -pdp_pool_set_max_mem_usage(int max) -{ - pdp_post("ERROR: mem limit not implemented"); -} - - - - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_post.c b/system/kernel/pdp_post.c deleted file mode 100644 index fb761d0..0000000 --- a/system/kernel/pdp_post.c +++ /dev/null @@ -1,48 +0,0 @@ - -/* - * Pure Data Packet system file. pdp logging. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include "pdp_post.h" - -/* list printing should be moved here too */ - -/* write a message to log (console) */ -void pdp_post_n(char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} -void pdp_post(char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - putc('\n', stderr); -} - - diff --git a/system/kernel/pdp_queue.c b/system/kernel/pdp_queue.c deleted file mode 100644 index 665a236..0000000 --- a/system/kernel/pdp_queue.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Pure Data Packet - processor queue module. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - - -/* - this is a the processor queue pdp system module - it receives tasks from objects that are schedules to - be computed in another thread. the object is signalled back - when the task is completed. - - this is not a standard pd class. it is a sigleton class - using a standard pd clock to poll for compleded methods on - every scheduler run. this is a hack to do thread synchronization - in a thread unsafe pd. - - the queue object can be reused. the pdp system however only - has one instance (one pdp queue. pdp remains a serial program.) - - */ - -#include "pdp.h" -#include <pthread.h> -#include <unistd.h> -#include <stdio.h> - - -#define D if (0) - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define PDP_QUEUE_LOGSIZE 10 -#define PDP_QUEUE_DELTIME 10.0f - - - - -/********************* general purpose pd process queue class *********************/ - -void pdp_procqueue_wait(t_pdp_procqueue *q) -{ - D post("pdp_procqueue_wait(%x): waiting for pdp_queue_thread to finish processing", q); - pthread_mutex_lock(&q->mut); - while(((q->curr - q->head) & q->mask) != 0){ - - pthread_cond_wait(&q->cond_processingdone, &q->mut); - } - pthread_mutex_unlock(&q->mut); - D post("pdp_procqueue_wait(%x): pdp_procqueue_thread has finished processing", q); - -} -void pdp_procqueue_finish(t_pdp_procqueue *q, int index) -{ - - if (-1 == index) { - //post("pdp_pq_remove: index == -1"); - return; - } - /* wait for processing thread to finish*/ - pdp_procqueue_wait(q); - - /* invalidate callback at index */ - q->q[index & q->mask].x_callback = 0; - q->q[index & q->mask].x_queue_id = 0; - -} - -static void pdp_procqueue_signal_processor(t_pdp_procqueue *q) -{ - - //NOTE: uncommenting these post statements causes a libc crash - //in mutex lock in putc - //D post("pdp_procqueue_signal_processor(%x): signalling process thread", q); - pthread_mutex_lock(&q->mut); - pthread_cond_signal(&q->cond_dataready); - pthread_mutex_unlock(&q->mut); - //D post("pdp_procqueue_signal_processor(%x): signalling done", q); - - -} - -static void pdp_procqueue_wait_for_feeder(t_pdp_procqueue *q) -{ - - - /* only use locking when there is no data */ - if(((q->curr - q->head) & q->mask) == 0){ - - /* signal processing done */ - D post("pdp_procqueue_wait_for_feeder(%x): signalling processing is done", q); - pthread_mutex_lock(&q->mut); - pthread_cond_signal(&q->cond_processingdone); - - /* wait until there is an item in the queue */ - while(((q->curr - q->head) & q->mask) == 0){ - pthread_cond_wait(&q->cond_dataready, &q->mut); - } - - pthread_mutex_unlock(&q->mut); - D post("pdp_procqueue_wait_for_feeder(%x): waiting done", q); - - } -} - -void pdp_procqueue_add(t_pdp_procqueue *q, void *owner, void *process, void *callback, int *queue_id) -{ - int i; - - /* if processing is in not in thread, just call the funcs */ - if (!q->use_thread){ - D post("pdp_procqueue_add(%q): calling processing routine directly", q); - if (queue_id) *queue_id = -1; - if (process) ((t_pdpmethod) process)(owner); - if (callback) ((t_pdpmethod) callback)(owner); - return; - } - - - /* if queue is full, call directly */ - if (1 == ((q->tail - q->head) & q->mask)) { - //post("pdp_procqueue_add: WARNING: processing queue (%x) is full.\n", q); - //post("pdp_procqueue_add: WARNING: tail %x, head %x, mask %x.\n", q->tail, q->head, q->mask); - //post("pdp_procqueue_add: WARNING: skipping process method, calling callback directly.\n"); - if (queue_id) *queue_id = -1; - if (callback) ((t_pdpmethod) callback)(owner); - return; - //exit(1); - } - - /* schedule method in thread queue */ - i = q->head & q->mask; - q->q[i].x_owner = owner; - q->q[i].x_process = process; - q->q[i].x_callback = callback; - q->q[i].x_queue_id = queue_id; - if (queue_id) *queue_id = i; - //post("pdp_queue_add: added method to queue, index %d", i); - - - // increase the packet count - q->packets++; - - // move head forward - q->head++; - - pdp_procqueue_signal_processor(q); - -} - - -/* processing thread */ -static void *pdp_procqueue_thread(void *vq) -{ - t_pdp_procqueue *q = (t_pdp_procqueue *)vq; - - D post("pdp_procqueue_thread(%x): thread started", q); - - while(1){ - t_process_queue_item *p; - - - D post("pdp_procqueue_thread(%x): waiting for feeder", q); - - /* wait until there is data available */ - pdp_procqueue_wait_for_feeder(q); - - - D post("pdp_procqueue_thread(%x): processing %d", q, q->curr & q->mask); - - - /* call the process routine */ - p = &q->q[q->curr & q->mask]; - if (p->x_process) - (p->x_process)(p->x_owner); - - /* advance */ - q->curr++; - - - } -} - - -/* call back all the callbacks */ -static void pdp_procqueue_callback (t_pdp_procqueue *q) -{ - - /* call callbacks for finished packets */ - while(0 != ((q->curr - q->tail) & q->mask)) - { - int i = q->tail & q->mask; - /* invalidate queue id */ - if(q->q[i].x_queue_id) *q->q[i].x_queue_id = -1; - /* call callback */ - if(q->q[i].x_callback) (q->q[i].x_callback)(q->q[i].x_owner); - //else post("pdp_pq_tick: callback %d is disabled",i ); - q->tail++; - } - -} - -/* the clock method */ -static void pdp_procqueue_tick (t_pdp_procqueue *q) -{ - /* do work */ - //if (!(ticks % 1000)) post("pdp tick %d", ticks); - - if (!q->use_thread) return; - - /* call callbacks */ - pdp_procqueue_callback(q); - - /* increase counter */ - q->ticks++; - - /* set clock for next update */ - clock_delay(q->pdp_clock, q->deltime); -} - - - -void pdp_procqueue_use_thread(t_pdp_procqueue* q, int t) -{ - /* if thread usage is being disabled, - wait for thread to finish processing first */ - if (t == 0) { - pdp_procqueue_wait(q); - q->use_thread = 0; - pdp_procqueue_callback(q); - clock_unset(q->pdp_clock); - } - else { - clock_unset(q->pdp_clock); - clock_delay(q->pdp_clock, q->deltime); - q->use_thread = 1; - } - -} - -void pdp_procqueue_init(t_pdp_procqueue *q, double milliseconds, int logsize) -{ - pthread_attr_t attr; - int size = 1 << logsize; - - /* setup pdp queue processor object */ - q->ticks = 0; - q->deltime = milliseconds; - - /* setup queue data */ - q->mask = size - 1; - q->head = 0; - q->tail = 0; - q->curr = 0; - q->q = pdp_alloc(size * sizeof(t_process_queue_item)); - memset(q->q, 0, size * sizeof(t_process_queue_item)); - - /* enable threads */ - q->use_thread = 1; - - /* setup synchro stuff */ - pthread_mutex_init(&q->mut, NULL); - pthread_cond_init(&q->cond_dataready, NULL); - pthread_cond_init(&q->cond_processingdone, NULL); - - - /* allocate the clock */ - q->pdp_clock = clock_new(q, (t_method)pdp_procqueue_tick); - - /* set the clock */ - clock_delay(q->pdp_clock, 0); - - /* start processing thread */ - - /* glibc doc says SCHED_OTHER is default, - but it seems not to be when initiated from a RT thread - so we explicitly set it here */ - pthread_attr_init (&attr); - //pthread_attr_setschedpolicy(&attr, SCHED_FIFO); - pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - - D post("pdp_procqueue_init(%x): starting thread", q); - pthread_create(&q->thread_id, &attr, pdp_procqueue_thread, (void *)q); - D post("pdp_procqueue_init(%x): back in pd thread", q); - - /* wait for processing thread to finish */ - //pdp_procqueue_wait(q); - - /* set default disable/enable thread here */ - //post("pdp_queue: THREAD PROCESSING ON BY DEFAULT!!"); - pdp_procqueue_use_thread(q,0); - -} - - - - -/* the (static) pdp queue object */ -static t_pdp_procqueue pdp_queue; - - -/* get the default queue */ -t_pdp_procqueue *pdp_queue_get_queue(void){return &pdp_queue;} - - -#if 1 -/* default pdp queue shortcut methods */ -void pdp_queue_wait() {pdp_procqueue_wait(&pdp_queue);} -void pdp_queue_finish(int index) { pdp_procqueue_finish(&pdp_queue, index);} -void pdp_queue_add(void *owner, void *process, void *callback, int *queue_id) { - pdp_procqueue_add(&pdp_queue, owner, process, callback, queue_id); -} -void pdp_queue_use_thread(int t) {pdp_procqueue_use_thread(&pdp_queue, t);} -void pdp_queue_setup(void){ - pdp_procqueue_init(&pdp_queue, PDP_QUEUE_DELTIME, PDP_QUEUE_LOGSIZE); - pdp_procqueue_use_thread(&pdp_queue,0); -} -#endif - - - - - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_symbol.c b/system/kernel/pdp_symbol.c deleted file mode 100644 index 32e9e33..0000000 --- a/system/kernel/pdp_symbol.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Pure Data Packet system implementation. : code implementing pdp's namespace (symbols) - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <string.h> -#include <pthread.h> -#include "pdp_symbol.h" -#include "pdp_list.h" -#include "pdp_debug.h" - -// some extra prototypes -void *pdp_alloc(int size); -void pdp_dealloc(void *data); - -// the symbol hash mutex -static pthread_mutex_t pdp_hash_mutex; - -#define HASHSIZE 1024 -static t_pdp_symbol *pdp_symhash[HASHSIZE]; - - -#define LOCK pthread_mutex_lock(&pdp_hash_mutex) -#define UNLOCK pthread_mutex_unlock(&pdp_hash_mutex) - - -static void _pdp_symbol_init(t_pdp_symbol *s) -{ - memset(s, 0, sizeof(*s)); - s->s_forth.t = a_undef; -} - - -/* shamelessly copied from pd src and made thread safe */ -t_pdp_symbol *_pdp_dogensym(char *s, t_pdp_symbol *oldsym) -{ - t_pdp_symbol **sym1, *sym2; - unsigned int hash1 = 0, hash2 = 0; - int length = 0; - char *s2 = s; - while (*s2) - { - hash1 += *s2; - hash2 += hash1; - length++; - s2++; - } - sym1 = pdp_symhash + (hash2 & (HASHSIZE-1)); - - /* lock hash */ - LOCK; - - while (sym2 = *sym1) - { - if (!strcmp(sym2->s_name, s)) goto gotit; - sym1 = &sym2->s_next; - } - if (oldsym){ - sym2 = oldsym; - } - else - { - sym2 = (t_pdp_symbol *)pdp_alloc(sizeof(*sym2)); - _pdp_symbol_init(sym2); - sym2->s_name = pdp_alloc(length+1); - sym2->s_next = 0; - strcpy(sym2->s_name, s); - } - *sym1 = sym2; - - gotit: - - /* unlock hash */ - UNLOCK; - return (sym2); -} - -t_pdp_symbol *pdp_gensym(char *s) -{ - return(_pdp_dogensym(s, 0)); -} - - -/* connect a parsed typelist to a symbol type name - 1 = succes, 0 = error (symbol already connected) */ -int pdp_symbol_set_typelist(t_pdp_symbol *s, t_pdp_list *typelist) -{ - int status = 0; - LOCK; - if (!s->s_type){ - s->s_type = typelist; - status = 1; - } - UNLOCK; - return status; -} - - -void pdp_symbol_apply_all(t_pdp_symbol_iterator it) -{ - int i; - for (i=0; i<HASHSIZE; i++){ - t_pdp_symbol *s; - for (s = pdp_symhash[i]; s; s=s->s_next){ - it(s); - } - - } -} - -t_pdp_symbol _pdp_sym_wildcard; -t_pdp_symbol _pdp_sym_float; -t_pdp_symbol _pdp_sym_int; -t_pdp_symbol _pdp_sym_symbol; -t_pdp_symbol _pdp_sym_packet; -t_pdp_symbol _pdp_sym_pointer; -t_pdp_symbol _pdp_sym_invalid; -t_pdp_symbol _pdp_sym_list; -t_pdp_symbol _pdp_sym_question_mark; -t_pdp_symbol _pdp_sym_atom; -t_pdp_symbol _pdp_sym_null; -t_pdp_symbol _pdp_sym_quote_start; -t_pdp_symbol _pdp_sym_quote_end; -t_pdp_symbol _pdp_sym_return; -t_pdp_symbol _pdp_sym_nreturn; -t_pdp_symbol _pdp_sym_defstart; -t_pdp_symbol _pdp_sym_defend; -t_pdp_symbol _pdp_sym_if; -t_pdp_symbol _pdp_sym_then; -t_pdp_symbol _pdp_sym_local; -t_pdp_symbol _pdp_sym_forth; -t_pdp_symbol _pdp_sym_call; -t_pdp_symbol _pdp_sym_push; -t_pdp_symbol _pdp_sym_pop; - -static void _sym(char *name, t_pdp_symbol *s) -{ - t_pdp_symbol *realsym; - _pdp_symbol_init(s); - s->s_name = name; - realsym = _pdp_dogensym(name, s); - PDP_ASSERT(realsym == s); // if this fails, the symbol was already defined -} - -void pdp_symbol_setup(void) -{ - // create mutexes - pthread_mutex_init(&pdp_hash_mutex, NULL); - - // init symbol hash - memset(pdp_symhash, 0, HASHSIZE * sizeof(t_pdp_symbol *)); - - // setup predefined symbols (those that have direct pointer access for speedup) - _sym("*", &_pdp_sym_wildcard); - _sym("float", &_pdp_sym_float); - _sym("int", &_pdp_sym_int); - _sym("symbol", &_pdp_sym_symbol); - _sym("packet", &_pdp_sym_packet); - _sym("pointer", &_pdp_sym_pointer); - _sym("invalid", &_pdp_sym_invalid); - _sym("list", &_pdp_sym_list); - _sym("?", &_pdp_sym_question_mark); - _sym("atom", &_pdp_sym_atom); - _sym("null", &_pdp_sym_null); - _sym("[", &_pdp_sym_quote_start); - _sym("]", &_pdp_sym_quote_end); - _sym("ret", &_pdp_sym_return); - _sym("nret", &_pdp_sym_nreturn); - _sym(":", &_pdp_sym_defstart); - _sym(";", &_pdp_sym_defend); - _sym("if", &_pdp_sym_if); - _sym("then", &_pdp_sym_then); - _sym("local", &_pdp_sym_local); - _sym("forth", &_pdp_sym_forth); - _sym("call", &_pdp_sym_call); - _sym("push", &_pdp_sym_push); - _sym("pop", &_pdp_sym_pop); - -} - - diff --git a/system/kernel/pdp_type.c b/system/kernel/pdp_type.c deleted file mode 100644 index c220269..0000000 --- a/system/kernel/pdp_type.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Pure Data Packet system implementation. : code for handling different packet types - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* this file contains type handling routines */ - -#include <stdarg.h> -#include <string.h> -#include <pthread.h> -#include "pdp.h" - - -// debug -#define D if (0) - - -static t_pdp_list *conversion_list; - -#define INIT_MAX_CACHE_SIZE 32 - -static t_pdp_list *cached_conversion_list; -static int max_cache_size; - -/* mutex */ -static pthread_mutex_t pdp_hash_mutex; -static pthread_mutex_t pdp_conversion_mutex; -static pthread_mutex_t pdp_cache_mutex; - -#define HASHSIZE 1024 -static t_pdp_symbol *pdp_symhash[HASHSIZE]; - - -/* shamelessly copied from pd src and made thread safe */ -t_pdp_symbol *_pdp_dogensym(char *s, t_pdp_symbol *oldsym) -{ - t_pdp_symbol **sym1, *sym2; - unsigned int hash1 = 0, hash2 = 0; - int length = 0; - char *s2 = s; - while (*s2) - { - hash1 += *s2; - hash2 += hash1; - length++; - s2++; - } - sym1 = pdp_symhash + (hash2 & (HASHSIZE-1)); - - /* lock hash */ - pthread_mutex_lock(&pdp_hash_mutex); - - while (sym2 = *sym1) - { - if (!strcmp(sym2->s_name, s)) goto gotit; - sym1 = &sym2->s_next; - } - if (oldsym) sym2 = oldsym; - else - { - sym2 = (t_pdp_symbol *)pdp_alloc(sizeof(*sym2)); - sym2->s_name = pdp_alloc(length+1); - _pdp_symbol_clear_namespaces(sym2); - sym2->s_next = 0; - strcpy(sym2->s_name, s); - } - *sym1 = sym2; - - gotit: - - /* unlock hash */ - pthread_mutex_unlock(&pdp_hash_mutex); - return (sym2); -} - -t_pdp_symbol *pdp_gensym(char *s) -{ - return(_pdp_dogensym(s, 0)); -} - -/* convert a type to a list */ -t_pdp_list *pdp_type_to_list(t_pdp_symbol *type) -{ - char *c = type->s_name; - char *lastname = c; - char tmp[100]; - int n = 0; - t_pdp_list *l = pdp_list_new(0); - - while(*c){ - if (*c == '/'){ - strncpy(tmp, lastname, n); - tmp[n] = 0; - pdp_list_add_back(l, a_symbol, (t_pdp_word)pdp_gensym(tmp)); - c++; - lastname = c; - n = 0; - } - else{ - c++; - n++; - } - } - pdp_list_add_back(l, a_symbol, (t_pdp_word)pdp_gensym(lastname)); - - return l; -} - - -/* get the description symbol. this includes some compat transition stuff with a warning */ -t_pdp_symbol *pdp_packet_get_description(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - - if (!header) return pdp_gensym("invalid"); - else if (!header->desc){ - - post("ERROR: pdp_packet_get_description: packet %d has no description.", packet); - pdp_packet_print_debug(packet); - return pdp_gensym("unknown"); - } - else return header->desc; -} - - - -/* this runs a conversion program */ -int _pdp_type_run_conversion_program(t_pdp_conversion_program *program, - int packet, t_pdp_symbol *dest_template) -{ - /* run a conversion program: - treat the source packet as readonly, and cleanup intermediates, such - that the net result is the production of a new packet, with the - source packet intact. */ - - int p, tmp; - t_pdp_atom *a; - t_pdp_conversion_method m; - - // run the first line of the program - a = program->first; - m = a->w.w_pointer; - D post("DEBUG: _pdp_type_run_conversion_program: method = %x", m); - p = m(packet, dest_template); - D post("DEBUG: _pdp_type_run_conversion_program: packet returned = %d, type = %s", p, pdp_packet_get_description(p)->s_name); - - // run the remaining lines + cleanup intermediates - for (a=a->next; a; a=a->next){ - m = a->w.w_pointer; - D post("DEBUG: _pdp_type_run_conversion_program: next method ptr = %x", m); - tmp = m(p, dest_template); - pdp_packet_mark_unused(p); - p = tmp; - } - return p; -} - - -/* find a conversion program */ -t_pdp_conversion_program * -_pdp_type_find_conversion_program(t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern) -{ - t_pdp_conversion *c; - t_pdp_atom *a; - t_pdp_conversion_program *retval = 0; - - /* lock conversion list */ - pthread_mutex_lock(&pdp_conversion_mutex); - - for (a = conversion_list->first; a; a=a->next){ - c = a->w.w_pointer; - /* can be a wildcard match */ - if (pdp_type_description_match(src_pattern, c->src_pattern) && - pdp_type_description_match(dst_pattern, c->dst_pattern)) { - /* found a program */ - D post("DEBUG: _pdp_type_find_conversion_program: found: %s -> %s", c->src_pattern->s_name, c->dst_pattern->s_name); - retval = c->program; - goto gotit; - } - } - - /* no conversion program was found */ - retval = 0; - gotit: - - /* lock conversion list */ - pthread_mutex_unlock(&pdp_conversion_mutex); - return retval; -} - -/* find a cached conversion program - if one is found it will be moved to the back of the queue (MRU) */ -t_pdp_conversion_program * -_pdp_type_find_cached_conversion_program(t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern) -{ - t_pdp_conversion *c, *c_tmp; - t_pdp_atom *a; - t_pdp_conversion_program *retval = 0; - - /* lock cached list */ - pthread_mutex_lock(&pdp_cache_mutex); - - for (a = cached_conversion_list->first; a; a=a->next){ - c = a->w.w_pointer; - /* must be exact match */ - if ((src_pattern == c->src_pattern) && - (dst_pattern == c->dst_pattern)) { - - /* found a program */ - D post("DEBUG: _pdp_type_find_cached_conversion_program: found: %s -> %s", c->src_pattern->s_name, c->dst_pattern->s_name); - retval = c->program; - - /* make MRU (move to back) */ - c_tmp = cached_conversion_list->last->w.w_pointer; - cached_conversion_list->last->w.w_pointer = c; - a->w.w_pointer = c_tmp; - goto gotit; - } - } - - retval = 0; - - gotit: - - - /* un lock cached list */ - pthread_mutex_unlock(&pdp_cache_mutex); - - /* no conversion program was found */ - return retval; -} - - -/* conversion program manipulations */ -void pdp_conversion_program_free(t_pdp_conversion_program *program) -{ - pdp_list_free(program); -} - -/* debug print */ -void _pdp_conversion_program_print(t_pdp_conversion_program *program) -{ - post("_pdp_conversion_program_print %x", program); - pdp_list_print(program); -} - -t_pdp_conversion_program *pdp_conversion_program_new(t_pdp_conversion_method method, ...) -{ - t_pdp_conversion_program *p = pdp_list_new(0); - t_pdp_conversion_method m = method; - va_list ap; - - D post("DEBUG: pdp_conversion_program_new:BEGIN"); - - pdp_list_add_back_pointer(p, m); - va_start(ap, method); - while (m = va_arg(ap, t_pdp_conversion_method)) pdp_list_add_back_pointer(p, m); - va_end(ap); - - D post("DEBUG: pdp_conversion_program_new:END"); - - return p; -} - -t_pdp_conversion_program *pdp_conversion_program_copy(t_pdp_conversion_program *program) -{ - if (program) return pdp_list_copy(program); - else return 0; -} - -void pdp_conversion_program_add(t_pdp_conversion_program *program, t_pdp_conversion_program *tail) -{ - return pdp_list_cat(program, tail); -} - -/* conversion registration */ -void pdp_type_register_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program) -{ - t_pdp_conversion *c = (t_pdp_conversion *)pdp_alloc(sizeof(*c)); - c->src_pattern = src_pattern; - c->dst_pattern = dst_pattern; - c->program = program; - - /* lock conversion list */ - pthread_mutex_lock(&pdp_conversion_mutex); - - pdp_list_add_back_pointer(conversion_list, c); - - /* unlock conversion list */ - pthread_mutex_unlock(&pdp_conversion_mutex); - -} - -/* register a cached conversion */ -void pdp_type_register_cached_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program) -{ - - /* create the new conversion */ - t_pdp_conversion *c = (t_pdp_conversion *)pdp_alloc(sizeof(*c)); - c->src_pattern = src_pattern; - c->dst_pattern = dst_pattern; - c->program = program; - - /* lock cached conversion list */ - pthread_mutex_lock(&pdp_cache_mutex); - - /* check size, and remove LRU (top) if the cache is full */ - while (cached_conversion_list->elements >= max_cache_size){ - t_pdp_conversion *c_old = pdp_list_pop(cached_conversion_list).w_pointer; - if (c_old->program) pdp_conversion_program_free(c_old->program); - pdp_dealloc(c_old); - } - - /* add and make MRU (back) */ - pdp_list_add_back_pointer(cached_conversion_list, c); - - /* unlock cached conversion list */ - pthread_mutex_unlock(&pdp_cache_mutex); -} - -/* convert a given packet to a certain type (template) */ -int _pdp_packet_convert(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - t_pdp_symbol *tmp_type = 0; - int tmp_packet = -1; - - t_pdp_conversion_program *program = 0; - t_pdp_conversion_program *program_last = 0; - t_pdp_conversion_program *program_tail = 0; - - /* check if there is a program in the cached list, if so run it */ - if (program = _pdp_type_find_cached_conversion_program(type, dest_template)) - return _pdp_type_run_conversion_program(program, packet, dest_template); - - /* if it is not cached, iteratively convert - and save program on top of cache list if a conversion path (program) was found */ - - // run first conversion that matches - program = pdp_conversion_program_copy(_pdp_type_find_conversion_program(type, dest_template)); - program_last = program; - if (!program){ - D post("DEBUG: pdp_type_convert: (1) can't convert %s to %s", type->s_name, dest_template->s_name); - return -1; - } - tmp_packet = _pdp_type_run_conversion_program(program, packet, dest_template); - tmp_type = pdp_packet_get_description(tmp_packet); - - // run more conversions if necessary, deleting intermediate packets - while (!pdp_type_description_match(tmp_type, dest_template)){ - int new_packet; - program_tail = _pdp_type_find_conversion_program(tmp_type, dest_template); - if (!program_tail){ - D post("DEBUG: pdp_type_convert: (2) can't convert %s to %s", tmp_type->s_name, dest_template->s_name); - pdp_packet_mark_unused(tmp_packet); - pdp_conversion_program_free(program); - return -1; - } - if (program_last == program_tail){ - post("ERROR: pdp_packet_convert: conversion loop detected"); - } - program_last = program_tail; - - pdp_conversion_program_add(program, program_tail); - new_packet = _pdp_type_run_conversion_program(program_tail, tmp_packet, dest_template); - pdp_packet_mark_unused(tmp_packet); - tmp_packet = new_packet; - tmp_type = pdp_packet_get_description(tmp_packet); - } - - // save the conversion program - pdp_type_register_cached_conversion(type, dest_template, program); - - // return resulting packet - return tmp_packet; - -} - -/* convert or copy ro */ -int pdp_packet_convert_ro(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - - /* if it is compatible, return a ro copy */ - if (pdp_type_description_match(type, dest_template)) return pdp_packet_copy_ro(packet); - - /* if not, convert to a new type */ - else return _pdp_packet_convert(packet, dest_template); -} - -/* convert or copy rw */ -int pdp_packet_convert_rw(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - - /* if it is compatible, just return a rw copy */ - if (pdp_type_description_match(type, dest_template)) return pdp_packet_copy_rw(packet); - - /* if not, convert to a new type */ - else return _pdp_packet_convert(packet, dest_template); -} - - -static void _setup_type_cache(t_pdp_symbol *s) -{ - t_pdp_list *l = pdp_type_to_list(s); - pthread_mutex_lock(&pdp_hash_mutex); //lock to prevent re-entry - if (!s->s_type){ - s->s_type = l; - l = 0; - } - pthread_mutex_unlock(&pdp_hash_mutex); - if (l) pdp_list_free(l); -} - -/* check if a type description fits a template - this function is symmetric */ -int pdp_type_description_match(t_pdp_symbol *description, t_pdp_symbol *pattern) -{ - int retval = 0; - - t_pdp_atom *ad, *ap; - t_pdp_symbol *wildcard = pdp_gensym("*"); - - - if (!(pattern)) post("PANICA"); - if (!(description)) post("PANICB"); - - - /* same type -> match */ - if (description == pattern) {retval = 1; goto done;} - - /* use the description list stored in the symbol for comparison */ - if (!(description->s_type)) _setup_type_cache(description); - if (!(pattern->s_type)) _setup_type_cache(pattern); - - if (!(pattern->s_type)) post("PANIC1"); - if (!(description->s_type)) post("PANIC2"); - - /* check size */ - if (description->s_type->elements != pattern->s_type->elements){retval = 0; goto done;} - - /* compare symbols of type list */ - for(ad=description->s_type->first, ap=pattern->s_type->first; ad; ad=ad->next, ap=ap->next){ - if (ad->w.w_symbol == wildcard) continue; - if (ap->w.w_symbol == wildcard) continue; - if (ad->w.w_symbol != ap->w.w_symbol) {retval = 0; goto done;} /* difference and not a wildcard */ - } - - /* type templates match */ - retval = 1; - - done: - D post("DEBUG: testing match between %s and %s: %s", - description->s_name, pattern->s_name, retval ? "match" : "no match"); - return retval; - -} - - - - - -/* setup method */ -void pdp_type_setup(void) -{ - int i; - - // create mutexes - pthread_mutex_init(&pdp_hash_mutex, NULL); - pthread_mutex_init(&pdp_conversion_mutex, NULL); - pthread_mutex_init(&pdp_cache_mutex, NULL); - - // init symbol hash - memset(pdp_symhash, 0, HASHSIZE * sizeof(t_pdp_symbol *)); - - // create conversion lists - cached_conversion_list = pdp_list_new(0); - conversion_list = pdp_list_new(0); - max_cache_size = INIT_MAX_CACHE_SIZE; - - - - -} diff --git a/system/kernel/pdp_type.c_old b/system/kernel/pdp_type.c_old deleted file mode 100644 index 4e42d53..0000000 --- a/system/kernel/pdp_type.c_old +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Pure Data Packet system implementation. : code for handling different packet types - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* this file contains type handling routines - note: pd symbols are used for type identification - for porting to other hosts, i suggest reimplementing t_pdp_symbol */ - -// debug - -#include <fnmatch.h> -#include <stdarg.h> -#include <string.h> -#include <pthread.h> -#include "pdp.h" - -/* - - - -*/ - - -#define D if (0) - - -static t_pdp_conversion *conversion_list; - -#define CACHE_SIZE 32 -static t_pdp_conversion *cached_conversion_list_start; -static t_pdp_conversion cached_conversion_array[CACHE_SIZE]; - -/* mutex */ -static pthread_mutex_t pdp_hash_mutex; -static pthread_mutex_t pdp_conversion_mutex; -static pthread_mutex_t pdp_cache_mutex; - -#define HASHSIZE 1024 -static t_pdp_symbol *pdp_symhash[HASHSIZE]; - - -/* shamelessly copied from pd src and made thread safe */ -t_pdp_symbol *_pdp_dogensym(char *s, t_pdp_symbol *oldsym) -{ - t_pdp_symbol **sym1, *sym2; - unsigned int hash1 = 0, hash2 = 0; - int length = 0; - char *s2 = s; - while (*s2) - { - hash1 += *s2; - hash2 += hash1; - length++; - s2++; - } - sym1 = pdp_symhash + (hash2 & (HASHSIZE-1)); - - /* lock hash */ - pthread_mutex_lock(&pdp_hash_mutex); - - while (sym2 = *sym1) - { - if (!strcmp(sym2->s_name, s)) goto gotit; - sym1 = &sym2->s_next; - } - if (oldsym) sym2 = oldsym; - else - { - sym2 = (t_pdp_symbol *)pdp_alloc(sizeof(*sym2)); - sym2->s_name = pdp_alloc(length+1); - _pdp_symbol_clear_namespaces(sym2); - sym2->s_next = 0; - strcpy(sym2->s_name, s); - } - *sym1 = sym2; - - gotit: - - /* unlock hash */ - pthread_mutex_unlock(&pdp_hash_mutex); - return (sym2); -} - -t_pdp_symbol *pdp_gensym(char *s) -{ - return(_pdp_dogensym(s, 0)); -} - -/* convert a type to a list */ -t_pdp_list *pdp_type_to_list(t_pdp_symbol *type) -{ - char *c = type->s_name; - char *lastname = c; - char tmp[100]; - int n = 0; - t_pdp_list *l = pdp_list_new(0); - - while(*c){ - if (*c == '/'){ - strncpy(tmp, lastname, n); - tmp[n] = 0; - pdp_list_add_back(l, a_symbol, (t_pdp_word)pdp_gensym(tmp)); - c++; - lastname = c; - n = 0; - } - else{ - c++; - n++; - } - } - pdp_list_add_back(l, a_symbol, (t_pdp_word)pdp_gensym(lastname)); - - return l; -} - - -/* get the description symbol. this includes some compat transition stuff with a warning */ -t_pdp_symbol *pdp_packet_get_description(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - - if (!header) return pdp_gensym("invalid"); - else if (!header->desc){ - /* if description is not defined, try to reconstruct it (for backwards compat) */ - if (header->type == PDP_IMAGE){ - post("FIXME: pdp_type_get_description: packet %d has no description. using workaround.", packet); - return pdp_packet_image_get_description(packet); - } - else - return pdp_gensym("unknown"); - } - else return header->desc; -} - - - -/* this runs a conversion program */ -int _pdp_type_run_conversion_program(t_pdp_conversion_program *program, - int packet, t_pdp_symbol *dest_template) -{ - /* run a conversion program: - treat the source packet as readonly, and cleanup intermediates, such - that the net result is the production of a new packet, with the - source packet intact. */ - - int p, tmp; - - D post("DEBUG: _pdp_type_run_conversion_program: program = %x", program); - - // run the first line of the program - D post("DEBUG: _pdp_type_run_conversion_program: method = %x", *program); - p = (*program->method)(packet, dest_template); - D post("DEBUG: _pdp_type_run_conversion_program: packet returned = %d, type = %s", p, pdp_packet_get_description(p)->s_name); - - // run the remaining lines + cleanup intermediates - for (program = program->next; program ; program = program->next){ - D post("DEBUG: _pdp_type_run_conversion_program: next method ptr = %x", *program->method); - tmp = (*program->method)(p, dest_template); - pdp_packet_mark_unused(p); - p = tmp; - } - return p; -} - - -/* find a conversion program */ -t_pdp_conversion_program * -_pdp_type_find_conversion_program(t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern) -{ - t_pdp_conversion *c; - t_pdp_conversion_program *retval = 0; - - /* lock conversion list */ - pthread_mutex_lock(&pdp_conversion_mutex); - - for (c = conversion_list; c; c=c->next){ - /* can be a wildcard match */ - if (pdp_type_description_match(src_pattern, c->src_pattern) && - pdp_type_description_match(dst_pattern, c->dst_pattern)) { - /* found a program */ - D post("DEBUG: _pdp_type_find_conversion_program: found: %s -> %s", c->src_pattern->s_name, c->dst_pattern->s_name); - retval = c->program; - goto gotit; - } - } - - /* no conversion program was found */ - retval = 0; - gotit: - - /* lock conversion list */ - pthread_mutex_unlock(&pdp_conversion_mutex); - return retval; -} - -/* find a cached conversion program */ -t_pdp_conversion_program * -_pdp_type_find_cached_conversion_program(t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern) -{ - t_pdp_conversion *c; - t_pdp_conversion_program *retval = 0; - - /* lock cached list */ - pthread_mutex_lock(&pdp_cache_mutex); - - for (c = cached_conversion_list_start; c; c=c->next){ - /* must be exact match */ - if ((src_pattern == c->src_pattern) && - (dst_pattern == c->dst_pattern)) { - /* found a program */ - D post("DEBUG: _pdp_type_find_cached_conversion_program: found: %s -> %s", c->src_pattern->s_name, c->dst_pattern->s_name); - retval = c->program; - goto gotit; - } - } - - retval = 0; - - gotit: - - /* un lock cached list */ - pthread_mutex_unlock(&pdp_cache_mutex); - - /* no conversion program was found */ - return retval; -} - - -/* conversion program manipulations */ -void pdp_conversion_program_free(t_pdp_conversion_program *program) -{ - t_pdp_conversion_program *p = 0; - while (program) { - p = program; - program = program->next; - pdp_dealloc (p); - } -} - -/* debug print */ -void _pdp_conversion_program_print(t_pdp_conversion_program *program) -{ - D post("DEBUG: conversion program: %x", program); - while(program){ - D post("DEBUG: method: %x", program->method); - program = program->next; - } -} - -t_pdp_conversion_program *pdp_conversion_program_new(t_pdp_conversion_method method, ...) -{ - t_pdp_conversion_program head; - t_pdp_conversion_program *p = &head; - t_pdp_conversion_method m = method; - va_list ap; - - D post("DEBUG: pdp_conversion_program_new:BEGIN"); - - p = p->next = (t_pdp_conversion_program *)pdp_alloc(sizeof(*p)); - p->method = m; - va_start(ap, method); - while (m = va_arg(ap, t_pdp_conversion_method)){ - p = p->next = (t_pdp_conversion_program *)pdp_alloc(sizeof(*p)); - p->method = m; - } - p->next = 0; // terminate list - va_end(ap); - - D post("DEBUG: pdp_conversion_program_new:END"); - D _pdp_conversion_program_print(head.next); - - return head.next; -} - -t_pdp_conversion_program *pdp_conversion_program_copy(t_pdp_conversion_program *program) -{ - t_pdp_conversion_program head; - t_pdp_conversion_program *p = &head; - - for(;program; program=program->next){ - p = p->next = (t_pdp_conversion_program *)pdp_alloc(sizeof(*p)); - p->method = program->method; - } - p->next = 0; - return head.next; -} - -void pdp_conversion_program_add(t_pdp_conversion_program *program, t_pdp_conversion_program *tail) -{ - t_pdp_conversion_program *p = program; - - //D post("DEBUG: pdp_conversion_program_add:BEGIN"); - - - while (p->next) p = p->next; - p->next = pdp_conversion_program_copy(tail); - - //D post("DEBUG: pdp_conversion_program_add:END"); - -} - -/* conversion registration */ -void pdp_type_register_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program) -{ - t_pdp_conversion head; - t_pdp_conversion *c = &head; - - /* lock conversion list */ - pthread_mutex_lock(&pdp_conversion_mutex); - - head.next = conversion_list; - - while (c->next) c=c->next; // add a new one to the end - c = c->next = (t_pdp_conversion *)pdp_alloc(sizeof(*c)); - c->src_pattern = src_pattern; - c->dst_pattern = dst_pattern; - c->program = program; - c->next = 0; - - conversion_list = head.next; - - /* unlock conversion list */ - pthread_mutex_unlock(&pdp_conversion_mutex); - -} - -/* register a cached conversion */ -void pdp_type_register_cached_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program) -{ - - t_pdp_conversion *save, *c, *c2; - - /* unlock cahed conversion list */ - pthread_mutex_lock(&pdp_cache_mutex); - - c2 = save = cached_conversion_list_start; - while (c2->next->next) c2 = c2->next; - c = c2->next; - c2->next = 0; - if (c->program) pdp_conversion_program_free(c->program); - c->src_pattern = src_pattern; - c->dst_pattern = dst_pattern; - c->program = program; - c->next = save; - cached_conversion_list_start = c; - - /* unlock cached conversion list */ - pthread_mutex_unlock(&pdp_cache_mutex); -} - -/* convert a given packet to a certain type (template) */ -int _pdp_packet_convert(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - t_pdp_symbol *tmp_type = 0; - int tmp_packet = -1; - - t_pdp_conversion_program *program = 0; - t_pdp_conversion_program *program_last = 0; - t_pdp_conversion_program *program_tail = 0; - - /* check if there is a program in the cached list, if so run it */ - if (program = _pdp_type_find_cached_conversion_program(type, dest_template)) - return _pdp_type_run_conversion_program(program, packet, dest_template); - - /* if it is not cached, iteratively convert - and save program on top of cache list if a conversion path (program) was found */ - - // run first conversion that matches - program = pdp_conversion_program_copy(_pdp_type_find_conversion_program(type, dest_template)); - program_last = program; - if (!program){ - D post("DEBUG: pdp_type_convert: (1) can't convert %s to %s", type->s_name, dest_template->s_name); - return -1; - } - tmp_packet = _pdp_type_run_conversion_program(program, packet, dest_template); - tmp_type = pdp_packet_get_description(tmp_packet); - - // run more conversions if necessary, deleting intermediate packets - while (!pdp_type_description_match(tmp_type, dest_template)){ - int new_packet; - program_tail = _pdp_type_find_conversion_program(tmp_type, dest_template); - if (!program_tail){ - D post("DEBUG: pdp_type_convert: (2) can't convert %s to %s", tmp_type->s_name, dest_template->s_name); - pdp_packet_mark_unused(tmp_packet); - pdp_conversion_program_free(program); - return -1; - } - if (program_last == program_tail){ - post("ERROR: pdp_packet_convert: conversion loop detected"); - } - program_last = program_tail; - - pdp_conversion_program_add(program, program_tail); - new_packet = _pdp_type_run_conversion_program(program_tail, tmp_packet, dest_template); - pdp_packet_mark_unused(tmp_packet); - tmp_packet = new_packet; - tmp_type = pdp_packet_get_description(tmp_packet); - } - - // save the conversion program - pdp_type_register_cached_conversion(type, dest_template, program); - - // return resulting packet - return tmp_packet; - -} - -/* convert or copy ro */ -int pdp_packet_convert_ro(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - - /* if it is compatible, return a ro copy */ - if (pdp_type_description_match(type, dest_template)) return pdp_packet_copy_ro(packet); - - /* if not, convert to a new type */ - else return _pdp_packet_convert(packet, dest_template); -} - -/* convert or copy rw */ -int pdp_packet_convert_rw(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - - /* if it is compatible, just return a rw copy */ - if (pdp_type_description_match(type, dest_template)) return pdp_packet_copy_rw(packet); - - /* if not, convert to a new type */ - else return _pdp_packet_convert(packet, dest_template); -} - - -static void _setup_type_cache(t_pdp_symbol *s) -{ - t_pdp_list *l = pdp_type_to_list(s); - pthread_mutex_lock(&pdp_hash_mutex); //lock to prevent re-entry - if (!s->s_type){ - s->s_type = l; - l = 0; - } - pthread_mutex_unlock(&pdp_hash_mutex); - if (l) pdp_list_free(l); -} - -/* check if a type description fits a template - this function is symmetric */ -int pdp_type_description_match(t_pdp_symbol *description, t_pdp_symbol *pattern) -{ - - -#if 1 - t_pdp_atom *ad, *ap; - t_pdp_symbol *wildcard = pdp_gensym("*"); - - /* same type -> match */ - if (description == pattern) return 1; - - /* use the description list stored in the symbol for comparison */ - if (!(description->s_type)) _setup_type_cache(description); - if (!(pattern->s_type)) _setup_type_cache(pattern); - - /* check size */ - if (description->s_type->elements != pattern->s_type->elements) return 0; - - /* compare symbols of type list */ - for(ad=description->s_type->first, ap=pattern->s_type->first; ad; ad=ad->next, ap=ap->next){ - if (ad->w.w_symbol == wildcard) continue; - if (ap->w.w_symbol == wildcard) continue; - if (ad->w.w_symbol != ap->w.w_symbol) return 0; /* difference and not a wildcard */ - } - - /* type templates match */ - return 1; - - -#else - int retval = 0; - if (description == pattern) retval = 1; - //else retval = (!fnmatch(pattern->s_name, description->s_name, FNM_FILE_NAME)); - - //hack: make a symmetric match symmetric by calling fnmatch a second time with reversed attributes - else retval = ((!fnmatch(pattern->s_name, description->s_name, FNM_FILE_NAME)) - ||(!fnmatch(description->s_name, pattern->s_name, FNM_FILE_NAME))); - - - D post("DEBUG: testing match between %s and %s: %s", description->s_name, pattern->s_name, retval ? "match" : "no match"); - - return retval; -#endif -} - - - - - -/* setup method */ -void pdp_type_setup(void) -{ - int i; - - // create mutexes - pthread_mutex_init(&pdp_hash_mutex, NULL); - pthread_mutex_init(&pdp_conversion_mutex, NULL); - pthread_mutex_init(&pdp_cache_mutex, NULL); - - // init hash - memset(pdp_symhash, 0, HASHSIZE * sizeof(t_pdp_symbol *)); - - // init conversion lists - conversion_list = 0; - for(i=0; i<CACHE_SIZE; i++){ - t_pdp_conversion *c = cached_conversion_array + i; - c->src_pattern = 0; - c->dst_pattern = 0; - c->program = 0; - c->next = c + 1; - } - cached_conversion_list_start = cached_conversion_array; - cached_conversion_array[CACHE_SIZE-1].next = 0; - - - -} diff --git a/system/kernel/pdp_ut.c b/system/kernel/pdp_ut.c deleted file mode 100644 index dadc493..0000000 --- a/system/kernel/pdp_ut.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Pure Data Packet - Utility toolkit objects. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* This file contains some small utility pd objects that make working with - pdp objects a lot easier. Mainly as glue to be used in the abstractions - in the distro. */ - - -#include "pdp.h" -#include <math.h> - -/* this object does an add, scale, clip operation */ - -t_class *pdp_ut_addscaleclip_class; - -typedef struct pdp_ut_addscaleclip_struct -{ - t_object x_obj; - t_outlet *x_outlet0; - t_float x_min; - t_float x_max; - t_float x_offset; - t_float x_scale; -} t_pdp_ut_addscaleclip; - - -static void pdp_ut_addscaleclip_float(t_pdp_ut_addscaleclip *x, t_floatarg f) -{ - f += x->x_offset; - f *= x->x_scale; - f = (f < x->x_min) ? x->x_min : f; - f = (f > x->x_max) ? x->x_max : f; - outlet_float(x->x_outlet0, f); -} - -static void pdp_ut_addscaleclip_free(t_pdp_ut_addscaleclip *x){} - -void *pdp_ut_addscaleclip_new(t_floatarg offset, t_floatarg scale, t_floatarg min, t_floatarg max) -{ - t_pdp_ut_addscaleclip *x = (t_pdp_ut_addscaleclip *)pd_new(pdp_ut_addscaleclip_class); - x->x_outlet0 = outlet_new(&x->x_obj, &s_float); - x->x_offset = offset; - x->x_scale = scale; - x->x_min = min; - x->x_max = max; - return (void *)x; -} - -void pdp_ut_addscaleclip_setup(void) -{ - pdp_ut_addscaleclip_class = class_new(gensym("pdp_ut_addscaleclip"), (t_newmethod)pdp_ut_addscaleclip_new, - (t_method)pdp_ut_addscaleclip_free, sizeof(t_pdp_ut_addscaleclip), 0, - A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addfloat(pdp_ut_addscaleclip_class, pdp_ut_addscaleclip_float); -} - - -/* pdp_ut_logmap does a logarithmic parameter mapping [0->1] x -> min(max/min)^x max an add, scale, clip operation */ -/* pdp_ut_logmap_comp does x -> min(max/min)^(1-x) */ -/* pdp_ut_linmap dos x -> min + (max - min * x */ - -t_class *pdp_ut_linmap_class; -t_class *pdp_ut_logmap_class; -t_class *pdp_ut_logmap_comp_class; - -typedef struct pdp_ut_map_struct -{ - t_object x_obj; - t_outlet *x_outlet0; - t_float x_min; - t_float x_max; -} t_pdp_ut_map; - - -static void pdp_ut_logmap_float(t_pdp_ut_map *x, t_floatarg f) -{ - f = (f < 0.0f) ? 0.0f : f; - f = (f > 1.0f) ? 1.0f : f; - - f = x->x_min * pow((x->x_max / x->x_min), f); - - outlet_float(x->x_outlet0, f); -} - -static void pdp_ut_linmap_float(t_pdp_ut_map *x, t_floatarg f) -{ - f = (f < 0.0f) ? 0.0f : f; - f = (f > 1.0f) ? 1.0f : f; - - f = x->x_min + ((x->x_max - x->x_min) * f); - - outlet_float(x->x_outlet0, f); -} - -static void pdp_ut_logmap_comp_float(t_pdp_ut_map *x, t_floatarg f) -{ - f = (f < 0.0f) ? 0.0f : f; - f = (f > 1.0f) ? 1.0f : f; - - f = x->x_min * pow((x->x_max / x->x_min), (1.0f - f)); - - outlet_float(x->x_outlet0, f); -} - -static void pdp_ut_map_free(t_pdp_ut_map *x){} - - -void pdp_ut_map_init(t_pdp_ut_map *x, t_floatarg min, t_floatarg max) -{ - x->x_outlet0 = outlet_new(&x->x_obj, &s_float); - x->x_min = min; - x->x_max = max; -} - -void *pdp_ut_logmap_new(t_floatarg min, t_floatarg max) -{ - t_pdp_ut_map *x = (t_pdp_ut_map *)pd_new(pdp_ut_logmap_class); - pdp_ut_map_init(x, min, max); - return (void *)x; -} - -void *pdp_ut_linmap_new(t_floatarg min, t_floatarg max) -{ - t_pdp_ut_map *x = (t_pdp_ut_map *)pd_new(pdp_ut_linmap_class); - pdp_ut_map_init(x, min, max); - return (void *)x; -} - -void *pdp_ut_logmap_comp_new(t_floatarg min, t_floatarg max) -{ - t_pdp_ut_map *x = (t_pdp_ut_map *)pd_new(pdp_ut_logmap_comp_class); - pdp_ut_map_init(x, min, max); - return (void *)x; -} - -void pdp_ut_logmap_setup(void) -{ - pdp_ut_logmap_class = class_new(gensym("pdp_ut_logmap"), (t_newmethod)pdp_ut_logmap_new, - (t_method)pdp_ut_map_free, sizeof(t_pdp_ut_map), 0, - A_FLOAT, A_FLOAT, A_NULL); - class_addfloat(pdp_ut_logmap_class, pdp_ut_logmap_float); -} - -void pdp_ut_logmap_comp_setup(void) -{ - pdp_ut_logmap_comp_class = class_new(gensym("pdp_ut_logmap_comp"), (t_newmethod)pdp_ut_logmap_comp_new, - (t_method)pdp_ut_map_free, sizeof(t_pdp_ut_map), 0, - A_FLOAT, A_FLOAT, A_NULL); - class_addfloat(pdp_ut_logmap_comp_class, pdp_ut_logmap_comp_float); -} - -void pdp_ut_linmap_setup(void) -{ - pdp_ut_linmap_class = class_new(gensym("pdp_ut_linmap"), (t_newmethod)pdp_ut_linmap_new, - (t_method)pdp_ut_map_free, sizeof(t_pdp_ut_map), 0, - A_FLOAT, A_FLOAT, A_NULL); - class_addfloat(pdp_ut_linmap_class, pdp_ut_linmap_float); -} - - - -t_class *pdp_ut_rgb2ycrcb_class; - -typedef struct pdp_ut_rgb2ycrcb -{ - t_object x_obj; - t_outlet *x_outlet_luma; - t_outlet *x_outlet_chroma_red; - t_outlet *x_outlet_chroma_blue; - - t_float x_red, x_green, x_blue; - -} t_pdp_ut_rgb2ycrcb; - - -static void pdp_ut_rgb2ycrcb_bang (t_pdp_ut_rgb2ycrcb* x) -{ - - float luma = 0.299f * x->x_red + 0.587f * x->x_green + 0.114f * x->x_blue; - float chroma_red = (x->x_red - luma) * 0.713f; - float chroma_blue = (x->x_blue - luma) * 0.565f; - - outlet_float(x->x_outlet_chroma_blue, chroma_blue); - outlet_float(x->x_outlet_chroma_red, chroma_red); - outlet_float(x->x_outlet_luma, luma); - -} - - -static void pdp_ut_rgb2ycrcb_red (t_pdp_ut_rgb2ycrcb* x, t_floatarg f) {x->x_red = f; pdp_ut_rgb2ycrcb_bang(x);} -static void pdp_ut_rgb2ycrcb_green (t_pdp_ut_rgb2ycrcb* x, t_floatarg f) {x->x_green = f; pdp_ut_rgb2ycrcb_bang(x);} -static void pdp_ut_rgb2ycrcb_blue (t_pdp_ut_rgb2ycrcb* x, t_floatarg f) {x->x_blue = f; pdp_ut_rgb2ycrcb_bang(x);} - - - -static void pdp_ut_rgb2ycrcb_free (t_pdp_ut_rgb2ycrcb* x) {} -static void* pdp_ut_rgb2ycrcb_new(void) -{ - t_pdp_ut_rgb2ycrcb *x = (t_pdp_ut_rgb2ycrcb *)pd_new(pdp_ut_rgb2ycrcb_class); - - - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("green")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("blue")); - - x->x_outlet_luma = outlet_new(&x->x_obj, &s_float); - x->x_outlet_chroma_red = outlet_new(&x->x_obj, &s_float); - x->x_outlet_chroma_blue = outlet_new(&x->x_obj, &s_float); - - x->x_red = 0.0f; - x->x_green = 0.0f; - x->x_blue = 0.0f; - - - return (void *)x; -} - -void pdp_ut_rgb2ycrcb_setup(void) -{ - pdp_ut_rgb2ycrcb_class = class_new(gensym("pdp_ut_rgb2ycrcb"), (t_newmethod)pdp_ut_rgb2ycrcb_new, - (t_method)pdp_ut_rgb2ycrcb_free, sizeof(t_pdp_ut_rgb2ycrcb), 0, A_NULL); - class_addfloat(pdp_ut_rgb2ycrcb_class, pdp_ut_rgb2ycrcb_red); - class_addmethod(pdp_ut_rgb2ycrcb_class, (t_method)pdp_ut_rgb2ycrcb_green, gensym("green"), A_FLOAT, A_NULL); - class_addmethod(pdp_ut_rgb2ycrcb_class, (t_method)pdp_ut_rgb2ycrcb_blue, gensym("blue"), A_FLOAT, A_NULL); -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - -void pdp_ut_setup(void) -{ - pdp_ut_addscaleclip_setup(); - pdp_ut_logmap_setup(); - pdp_ut_logmap_comp_setup(); - pdp_ut_linmap_setup(); - pdp_ut_rgb2ycrcb_setup(); -} - - -#ifdef __cplusplus -} -#endif |