aboutsummaryrefslogtreecommitdiff
path: root/system/pdp_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'system/pdp_packet.c')
-rw-r--r--system/pdp_packet.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/system/pdp_packet.c b/system/pdp_packet.c
new file mode 100644
index 0000000..0c0b2c2
--- /dev/null
+++ b/system/pdp_packet.c
@@ -0,0 +1,239 @@
+/*
+ * Pure Data Packet system implementation:
+ * code for allocation/deallocation/copying/...
+ * 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>
+
+/* all symbols are C style */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* this needs to be able to grow dynamically, think about it later */
+#define PDP_OBJECT_ARRAY_SIZE 1024
+static t_pdp* pdp_stack[PDP_OBJECT_ARRAY_SIZE];
+
+
+/* some global vars */
+static t_symbol* pdp_sym_register_rw;
+static t_symbol* pdp_sym_register_ro;
+static t_symbol* pdp_sym_process;
+
+
+/* setup methods */
+
+void
+pdp_packet_setup(void)
+{
+ bzero(pdp_stack, PDP_OBJECT_ARRAY_SIZE * sizeof(t_pdp *));
+ pdp_sym_register_rw = gensym("register_rw");
+ pdp_sym_register_ro = gensym("register_ro");
+ pdp_sym_process = gensym("process");
+}
+
+void
+pdp_packet_destroy(void)
+{
+ int i = 0;
+ /* dealloc all the data in object stack */
+ while ((i < PDP_OBJECT_ARRAY_SIZE) && (pdp_stack[i])) free(pdp_stack[i++]);
+}
+
+
+/* private pdp_mem methods */
+
+
+/* public object manips */
+
+
+/* alloc method: alloc time is linear in the number of used packets */
+/* think about a better (tree) method when this number grows large */
+int
+pdp_packet_new(unsigned int datatype, unsigned int datasize /*without header*/)
+{
+ unsigned int totalsize = datasize + PDP_HEADER_SIZE;
+ int i = 0;
+ unsigned int align;
+ t_pdp* p;
+ for (i=0; i < PDP_OBJECT_ARRAY_SIZE; i++){
+ p = pdp_stack[i];
+ /* check if we can reuse this one if it is already allocated */
+ if (p) {
+ /* remark: if p->size >= totalsize we can give away the packet */
+ /* but that would lead to unefficient use if we have a lot of packets */
+ /* of different sizes */
+ if ((p->users == 0) && (p->size == totalsize) && (p->type == datatype)){
+ //post("pdp_new_object: can reuse %d", i);
+ p->users = 1;
+ return i;
+ }
+ else{
+ //post("pdp_new_object: can't reuse %d, (%d users)", i, p->users);
+ //post("size:%d, newsize:%d, type:%d, newtype:%d", p->size, totalsize, p->type, datatype);
+ }
+ }
+ /* allocate new one */
+ else {
+ p = (t_pdp *)malloc(totalsize);
+ align = ((unsigned int)p) & (PDP_ALIGN - 1);
+ if (align) post("pdp_new_object: warning data misaligned by %x", align);
+ pdp_stack[i] = p;
+ p->type = datatype;
+ p->size = totalsize;
+ p->users = 1;
+ //post("pdp_new_object: allocating new (%d)", i);
+ return i;
+ }
+ }
+ post("pdp_new_object: WARNING: out of memory");
+
+ return -1;
+
+}
+
+
+t_pdp*
+pdp_packet_header(int handle)
+{
+ if ((handle >= 0) && (handle < PDP_OBJECT_ARRAY_SIZE)) return pdp_stack[handle];
+ else return 0;
+}
+
+void*
+pdp_packet_data(int handle)
+{
+ if ((handle >= 0) && (handle < PDP_OBJECT_ARRAY_SIZE))
+ return (char *)(pdp_stack[handle]) + PDP_HEADER_SIZE;
+ else return 0;
+}
+
+
+
+int
+pdp_packet_copy_ro(int handle)
+{
+ int out_handle;
+
+ t_pdp* p;
+ if ((handle >= 0)
+ && (handle < PDP_OBJECT_ARRAY_SIZE)
+ && (p = pdp_stack[handle])){
+ /* increase the number of users and return */
+ p->users++;
+ out_handle = handle;
+ }
+ else out_handle = -1;
+
+ //post("pdp_copy_ro: outhandle:%d", out_handle);
+
+ return out_handle;
+}
+
+int
+pdp_packet_copy_rw(int handle)
+{
+ int out_handle;
+
+ t_pdp* p;
+ if ((handle >= 0)
+ && (handle < PDP_OBJECT_ARRAY_SIZE)
+ && (p = pdp_stack[handle])){
+ /* if there are other users, copy the object otherwize return the same handle */
+ if (p->users){
+ int new_handle = pdp_packet_new(p->type, p->size - PDP_HEADER_SIZE);
+ t_pdp* new_p = pdp_packet_header(new_handle);
+ memcpy(new_p, p, p->size);
+ new_p->users = 1;
+ out_handle = new_handle;
+ }
+ else {
+ p->users++;
+ out_handle = handle;
+ }
+ //post("pdp_copy_rw: inhandle:%d outhandle:%d", handle, out_handle);
+
+ }
+ else out_handle = -1;
+
+ return out_handle;
+}
+
+int
+pdp_packet_clone_rw(int handle)
+{
+ int out_handle;
+
+ t_pdp* p;
+ if ((handle >= 0)
+ && (handle < PDP_OBJECT_ARRAY_SIZE)
+ && (p = pdp_stack[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);
+ memcpy(new_p, p, PDP_HEADER_SIZE);
+ new_p->users = 1;
+ out_handle = new_handle;
+ }
+
+ else out_handle = -1;
+
+ return out_handle;
+}
+
+void
+pdp_packet_mark_unused(int handle)
+{
+ t_pdp* p;
+ if ((handle >= 0) && (handle < PDP_OBJECT_ARRAY_SIZE)){
+ if (p = pdp_stack[handle]) {
+ if (p->users) {
+ p->users--;
+ //post("pdp_mark_unused: handle %d, users left %d", handle, p->users);
+ }
+ else {
+ post("pdp_mark_unused: WARNING: handle %d has zero users (duplicate pdp_mark_unused ?)", handle);
+ }
+ }
+ else {
+ post("pdp_mark_unused: WARNING: 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);
+ }
+
+
+}
+
+/* remark. if an owner frees a rw copy, he can still pass it along to clients.
+the first copy instruction revives the object. maybe free should not be called free but unregister.
+as long as no new_object method is called, or no copy on another object is performed,
+the "undead" copy can be revived. this smells a bit, i know...*/
+
+
+
+
+#ifdef __cplusplus
+}
+#endif