On 2015-11-19 09:49, IOhannes m zmoelnig wrote:
> to keep the performance of a heap allocated buffer, i would suggest to:
> - use the original scheme for an "immediate" (non-recursive) message
> - detect recursion, and if so, allocate buffers on the stack.

attached is a patch that implements that.
the patch is against current HEAD, though i really worked on HEAD~1, so
it reverts a number of (imho unneccessary) things.

it only touches functions that actually do output things (minus the
revert-last-commit),

fgmaf
IOhannes
Index: packOSC.c
===================================================================
--- packOSC.c	(Revision 17594)
+++ packOSC.c	(Arbeitskopie)
@@ -208,7 +208,7 @@
 static int OSC_effectiveStringLength(char *string);
 
 static t_class *packOSC_class;
-#define NUM_OSC_BUFS 2
+
 typedef struct _packOSC
 {
     t_object    x_obj;
@@ -215,11 +215,11 @@
     int         x_typetags; /* typetag flag */
     int         x_timeTagOffset;
     int         x_bundle; /* bundle open flag */
-    OSCbuf      x_oscbuf[NUM_OSC_BUFS]; /* OSCbuffer */
+    OSCbuf      x_oscbuf[1]; /* OSCbuffer */
     t_outlet    *x_bdpthout; /* bundle-depth floatoutlet */
     t_outlet    *x_listout; /* OSC packet list ouput */
     size_t      x_buflength; /* number of elements in x_bufferForOSCbuf and x_bufferForOSClist */
-    char        *x_bufferForOSCbuf[NUM_OSC_BUFS]; /*[SC_BUFFER_SIZE];*/
+    char        *x_bufferForOSCbuf; /*[SC_BUFFER_SIZE];*/
     t_atom      *x_bufferForOSClist; /*[SC_BUFFER_SIZE];*/
     char        *x_prefix;
     int         x_reentry_count;
@@ -247,20 +247,15 @@
 
 static void *packOSC_new(void)
 {
-    int i;
-
     t_packOSC *x = (t_packOSC *)pd_new(packOSC_class);
     x->x_typetags = 1; /* set typetags to 1 by default */
     x->x_bundle = 0; /* bundle is closed */
     x->x_buflength = SC_BUFFER_SIZE;
-    for (i = 0; i < NUM_OSC_BUFS; ++i)
+    x->x_bufferForOSCbuf = (char *)getbytes(sizeof(char)*x->x_buflength);
+    if(x->x_bufferForOSCbuf == NULL)
     {
-        x->x_bufferForOSCbuf[i] = (char *)getbytes(sizeof(char)*x->x_buflength);
-        if(x->x_bufferForOSCbuf[i] == NULL)
-        {
-            pd_error(x, "packOSC: unable to allocate %lu bytes for x_bufferForOSCbuf", (long)(sizeof(char)*x->x_buflength));
-            goto fail;
-        }
+        pd_error(x, "packOSC: unable to allocate %lu bytes for x_bufferForOSCbuf", (long)(sizeof(char)*x->x_buflength));
+        goto fail;
     }
     x->x_bufferForOSClist = (t_atom *)getbytes(sizeof(t_atom)*x->x_buflength);
     if(x->x_bufferForOSClist == NULL)
@@ -268,8 +263,8 @@
         pd_error(x, "packOSC: unable to allocate %lu bytes for x_bufferForOSClist", (long)(sizeof(t_atom)*x->x_buflength));
         goto fail;
     }
-    for (i = 0; i < NUM_OSC_BUFS; ++i)
-        OSC_initBuffer(&x->x_oscbuf[i], x->x_buflength, x->x_bufferForOSCbuf[i]);
+    if (x->x_oscbuf != NULL)
+        OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf);
     x->x_listout = outlet_new(&x->x_obj, &s_list);
     x->x_bdpthout = outlet_new(&x->x_obj, &s_float);
     x->x_timeTagOffset = -1; /* immediately */
@@ -276,8 +271,7 @@
     x->x_reentry_count = 0;
     return (x);
 fail:
-    for (i = 0; i < NUM_OSC_BUFS; ++i)
-        if(x->x_bufferForOSCbuf[i] != NULL) freebytes(x->x_bufferForOSCbuf[i], (long)(sizeof(char)*x->x_buflength));
+    if(x->x_bufferForOSCbuf != NULL) freebytes(x->x_bufferForOSCbuf, (long)(sizeof(char)*x->x_buflength));
     if(x->x_bufferForOSClist != NULL) freebytes(x->x_bufferForOSClist, (long)(sizeof(char)*x->x_buflength));
     return NULL;
 }
@@ -301,34 +295,34 @@
 static void packOSC_openbundle(t_packOSC *x)
 {
     int result;
-
+    t_float bundledepth=(t_float)x->x_oscbuf->bundleDepth;
     if (x->x_timeTagOffset == -1)
-        result = OSC_openBundle(&x->x_oscbuf[x->x_reentry_count], OSCTT_Immediately());
+        result = OSC_openBundle(x->x_oscbuf, OSCTT_Immediately());
     else
-        result = OSC_openBundle(&x->x_oscbuf[x->x_reentry_count], OSCTT_CurrentTimePlusOffset((uint32_t)x->x_timeTagOffset));
+        result = OSC_openBundle(x->x_oscbuf, OSCTT_CurrentTimePlusOffset((uint32_t)x->x_timeTagOffset));
     if (result != 0)
     { /* reset the buffer */
-        OSC_initBuffer(&x->x_oscbuf[x->x_reentry_count], x->x_buflength, x->x_bufferForOSCbuf[x->x_reentry_count]);
+        OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf);
         x->x_bundle = 0;
     }
     else x->x_bundle = 1;
-    outlet_float(x->x_bdpthout, (float)x->x_oscbuf[x->x_reentry_count].bundleDepth);
+    outlet_float(x->x_bdpthout, bundledepth);
 }
 
 static void packOSC_closebundle(t_packOSC *x)
 {
-    if (OSC_closeBundle(&x->x_oscbuf[x->x_reentry_count]))
+    t_float bundledepth=(t_float)x->x_oscbuf->bundleDepth;
+    if (OSC_closeBundle(x->x_oscbuf))
     {
         pd_error(x, "packOSC: Problem closing bundle.");
         return;
     }
-    outlet_float(x->x_bdpthout, (float)x->x_oscbuf[x->x_reentry_count].bundleDepth);
+    outlet_float(x->x_bdpthout, bundledepth);
     /* in bundle mode we send when bundle is closed */
-    if(!OSC_isBufferEmpty(&x->x_oscbuf[x->x_reentry_count]) > 0 && OSC_isBufferDone(&x->x_oscbuf[x->x_reentry_count]))
+    if(!OSC_isBufferEmpty(x->x_oscbuf) > 0 && OSC_isBufferDone(x->x_oscbuf))
     {
+        x->x_bundle = 0; /* call this before _sendbuffer() to be ready for recursive calls */
         packOSC_sendbuffer(x);
-        OSC_initBuffer(&x->x_oscbuf[x->x_reentry_count], x->x_buflength, x->x_bufferForOSCbuf[x->x_reentry_count]);
-        x->x_bundle = 0;
         return;
     }
 }
@@ -341,18 +335,17 @@
 
 static void packOSC_setbufsize(t_packOSC *x, t_floatarg f)
 {
-    if (x->x_bufferForOSCbuf[x->x_reentry_count] != NULL)
-        freebytes((void *)x->x_bufferForOSCbuf[x->x_reentry_count], sizeof(char)*x->x_buflength);
+    if (x->x_bufferForOSCbuf != NULL) freebytes((void *)x->x_bufferForOSCbuf, sizeof(char)*x->x_buflength);
     if (x->x_bufferForOSClist != NULL) freebytes((void *)x->x_bufferForOSClist, sizeof(t_atom)*x->x_buflength);
     post("packOSC: bufsize arg is %f (%lu)", f, (long)f);
     x->x_buflength = (long)f;
-    x->x_bufferForOSCbuf[x->x_reentry_count] = (char *)getbytes(sizeof(char)*x->x_buflength);
-    if(x->x_bufferForOSCbuf[x->x_reentry_count] == NULL)
+    x->x_bufferForOSCbuf = (char *)getbytes(sizeof(char)*x->x_buflength);
+    if(x->x_bufferForOSCbuf == NULL)
         pd_error(x, "packOSC unable to allocate %lu bytes for x_bufferForOSCbuf", (long)(sizeof(char)*x->x_buflength));
     x->x_bufferForOSClist = (t_atom *)getbytes(sizeof(t_atom)*x->x_buflength);
     if(x->x_bufferForOSClist == NULL)
         pd_error(x, "packOSC unable to allocate %lu bytes for x_bufferForOSClist", (long)(sizeof(t_atom)*x->x_buflength));
-    OSC_initBuffer(&x->x_oscbuf[x->x_reentry_count], x->x_buflength, x->x_bufferForOSCbuf[x->x_reentry_count]);
+    OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf);
     post("packOSC: bufsize is now %d",x->x_buflength);
 }
 
@@ -375,11 +368,6 @@
     unsigned int    m, j, k;
     char            c;
 
-    if (x->x_reentry_count > NUM_OSC_BUFS)
-    {
-        pd_error(x, "packOSC: reentry count %d exceeds limit.", x->x_reentry_count);
-        return;
-    }
     x->x_reentry_count++;
     if (args == NULL)
     {
@@ -470,7 +458,7 @@
                 ++k;
             }
         }
-        if(packOSC_writetypedmessage(x, &x->x_oscbuf[x->x_reentry_count-1], messageName, nArgs, args, typeStr))
+        if(packOSC_writetypedmessage(x, x->x_oscbuf, messageName, nArgs, args, typeStr))
         {
             pd_error(x, "packOSC: usage error, packOSC_writetypedmessage failed.");
             goto cleanup;
@@ -500,7 +488,7 @@
             post("packOSC:   type-id: %d\n", args[i].type);
 #endif
         }
-        if(packOSC_writemessage(x, &x->x_oscbuf[x->x_reentry_count-1], messageName, i, args))
+        if(packOSC_writemessage(x, x->x_oscbuf, messageName, i, args))
         {
             pd_error(x, "packOSC: usage error, packOSC_writemessage failed.");
             goto cleanup;
@@ -510,7 +498,6 @@
     if(!x->x_bundle)
     {
         packOSC_sendbuffer(x);
-        OSC_initBuffer(&x->x_oscbuf[x->x_reentry_count-1], x->x_buflength, x->x_bufferForOSCbuf[x->x_reentry_count-1]);
     }
 
 cleanup:
@@ -559,9 +546,7 @@
 
 static void packOSC_free(t_packOSC *x)
 {
-    int i;
-    for (i = 0; i < NUM_OSC_BUFS; ++i)
-        if (x->x_bufferForOSCbuf[i] != NULL) freebytes((void *)x->x_bufferForOSCbuf[i], sizeof(char)*x->x_buflength);
+    if (x->x_bufferForOSCbuf != NULL) freebytes((void *)x->x_bufferForOSCbuf, sizeof(char)*x->x_buflength);
     if (x->x_bufferForOSClist != NULL) freebytes((void *)x->x_bufferForOSClist, sizeof(t_atom)*x->x_buflength);
 }
 
@@ -897,30 +882,49 @@
     int             i;
     int             length;
     unsigned char   *buf;
-    int             buf_index = (x->x_reentry_count == 0)?0:x->x_reentry_count-1; // bundles have reentry_count == 0
+    int             reentry_count=x->x_reentry_count;      /* must be on stack for recursion */
+    size_t          bufsize=sizeof(t_atom)*x->x_buflength; /* must be on stack for recursion */
+    t_atom          *atombuffer=x->x_bufferForOSClist;     /* must be on stack in the case of recursion */
 
+    if(reentry_count>0) /* if we are recurse, let's move atombuffer to the stack */
+        atombuffer=(t_atom *)getbytes(bufsize);
+
+    if(!atombuffer) {
+        pd_error(x, "packOSC: unable to allocate %lu bytes for atombuffer", (long)bufsize);
+        return 0;
+    }
+
 #ifdef DEBUG
     post("packOSC_sendbuffer: Sending buffer...\n");
 #endif
-    if (OSC_isBufferEmpty(&x->x_oscbuf[buf_index]))
+    if (OSC_isBufferEmpty(x->x_oscbuf))
     {
         post("packOSC_sendbuffer() called but buffer empty");
         return;
     }
-    if (!OSC_isBufferDone(&x->x_oscbuf[buf_index]))
+    if (!OSC_isBufferDone(x->x_oscbuf))
     {
         post("packOSC_sendbuffer() called but buffer not ready!, not exiting");
         return;
     }
-    length = OSC_packetSize(&x->x_oscbuf[buf_index]);
-    buf = (unsigned char *)OSC_getPacket(&x->x_oscbuf[buf_index]);
+    length = OSC_packetSize(x->x_oscbuf);
+    buf = (unsigned char *)OSC_getPacket(x->x_oscbuf);
 #ifdef DEBUG
     post ("packOSC_sendbuffer: length: %lu", length);
 #endif
+
     /* convert the bytes in the buffer to floats in a list */
-    for (i = 0; i < length; ++i) SETFLOAT(&x->x_bufferForOSClist[i], buf[i]);
+    for (i = 0; i < length; ++i) SETFLOAT(&atombuffer[i], buf[i]);
+
+    /* cleanup the OSCbuffer structure (so we are ready for recursion) */
+    OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf);
+
     /* send the list out the outlet */
-    outlet_list(x->x_listout, &s_list, length, x->x_bufferForOSClist);
+    outlet_list(x->x_listout, &s_list, length, atombuffer);
+
+    /* cleanup our 'stack'-allocated atombuffer in the case of reentrancy */
+    if(reentry_count>0)
+        freebytes(atombuffer, bufsize);
 }
 
 /* The next part is copied and morphed from OSC-client.c. */

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Pd-dev mailing list
[email protected]
http://lists.puredata.info/listinfo/pd-dev

Reply via email to