Revision: 76613
          http://sourceforge.net/p/brlcad/code/76613
Author:   starseeker
Date:     2020-07-31 19:18:16 +0000 (Fri, 31 Jul 2020)
Log Message:
-----------
Further restructuring of the callback mechanisms for subprocess I/O.

Modified Paths:
--------------
    brlcad/branches/bioh/include/ged/defines.h
    brlcad/branches/bioh/include/tclcad.h
    brlcad/branches/bioh/src/libged/ged_util.c
    brlcad/branches/bioh/src/libged/rtcheck/rtcheck.c
    brlcad/branches/bioh/src/libged/rtwizard/rtwizard.c
    brlcad/branches/bioh/src/libtclcad/tclcad_obj.c
    brlcad/branches/bioh/src/mged/setup.c

Modified: brlcad/branches/bioh/include/ged/defines.h
===================================================================
--- brlcad/branches/bioh/include/ged/defines.h  2020-07-31 16:00:56 UTC (rev 
76612)
+++ brlcad/branches/bioh/include/ged/defines.h  2020-07-31 19:18:16 UTC (rev 
76613)
@@ -250,11 +250,21 @@
     void                       (*ged_create_vlist_callback)(struct 
display_list *);    /**< @brief  function to call after all vlist created that 
loops through creating display list for each solid  */
     void                       (*ged_free_vlist_callback)(unsigned int, int);  
/**< @brief  function to call after freeing a vlist */
 
-    /* Handler functions for I/O communication with asynchronous subprocess 
commands */
+    /* Handler functions for I/O communication with asynchronous subprocess 
commands.  There
+     * are two opaque data structures at play here, with different scopes.  
One is the "data"
+     * pointer passed to ged_create_io_handler, which is used to store 
command-specific
+     * information internal to the library (the simplest thing to do is pass 
ged_subprocess
+     * in as the data pointer, but if that's not enough - see for example 
rtcheck - this
+     * mechanism allows for more elaborate measures.
+     *
+     * The second is ged_io_data, which is set in gedp by the calling 
application.  This is where
+     * information specific to the parent's I/O environment (which by 
definition the library
+     * can't know about as it is application specific) lives.  It should be 
assigned in the
+     * applications gedp before any calls to ged_create_io_handler are made.
+     * */
+    void (*ged_create_io_handler)(struct ged_subprocess *gp, int fd, 
ged_io_handler_callback_t callback, void *data);
+    void (*ged_delete_io_handler)(struct ged_subprocess *gp, int fd);
     void *ged_io_data;  /**< brief caller supplied data */
-    int io_mode;
-    void (*ged_create_io_handler)(void **chan, struct bu_process *p, int fd, 
int mode, void *data, ged_io_handler_callback_t callback);
-    void (*ged_delete_io_handler)(void *interp, void *chan, struct bu_process 
*p, int fd);
 
     // Other callbacks...
     // Tcl command strings - these are libtclcad level callbacks that execute 
user supplied Tcl commands if set:

Modified: brlcad/branches/bioh/include/tclcad.h
===================================================================
--- brlcad/branches/bioh/include/tclcad.h       2020-07-31 16:00:56 UTC (rev 
76612)
+++ brlcad/branches/bioh/include/tclcad.h       2020-07-31 19:18:16 UTC (rev 
76613)
@@ -514,16 +514,17 @@
 TCLCAD_EXPORT extern int tclcad_init(Tcl_Interp *interp, int init_gui, struct 
bu_vls *tlog);
 
 /**
- * Create Tcl specific I/O handlers
+ * Tcl specific I/O handlers
  */
+struct tclcad_io_data {
+    Tcl_Channel chan;
+    Tcl_Interp *interp;
+    int io_mode;
+};
 TCLCAD_EXPORT void
-tclcad_create_io_handler(void **chan, struct bu_process *p, int fd, int mode, 
void *data, ged_io_handler_callback_t callback);
-
-/**
- * Delete Tcl specific I/O handlers
- */
+tclcad_create_io_handler(struct ged_subprocess *p, int fd, 
ged_io_handler_callback_t callback, void *data);
 TCLCAD_EXPORT void
-tclcad_delete_io_handler(void *interp, void *chan, struct bu_process *p, int 
fd);
+tclcad_delete_io_handler(struct ged_subprocess *p, int fd);
 
 
 /* dm_tcl.c */

Modified: brlcad/branches/bioh/src/libged/ged_util.c
===================================================================
--- brlcad/branches/bioh/src/libged/ged_util.c  2020-07-31 16:00:56 UTC (rev 
76612)
+++ brlcad/branches/bioh/src/libged/ged_util.c  2020-07-31 19:18:16 UTC (rev 
76613)
@@ -1297,27 +1297,19 @@
     }
 }
 
-struct _ged_rt_client_data {
-    struct ged_subprocess *rrtp;
-    void *u_data;
-};
-
 void
 _ged_rt_output_handler(void *clientData, int UNUSED(mask))
 {
-    struct _ged_rt_client_data *drcdp = (struct _ged_rt_client_data 
*)clientData;
+    struct ged_subprocess *rrtp = (struct ged_subprocess *)clientData;
     int count = 0;
     int retcode = 0;
     int read_failed = 0;
     char line[RT_MAXLINE+1] = {0};
 
-    if ((drcdp == (struct _ged_rt_client_data *)NULL) ||
-       (drcdp->rrtp == (struct ged_subprocess *)NULL) ||
-       (drcdp->rrtp->gedp == (struct ged *)NULL))
+    if ((rrtp == (struct ged_subprocess *)NULL) || (rrtp->gedp == (struct ged 
*)NULL))
        return;
 
-    struct ged *gedp = drcdp->rrtp->gedp;
-    struct ged_subprocess *rrtp = drcdp->rrtp;
+    struct ged *gedp = rrtp->gedp;
 
     /* Get data from rt */
     if (bu_process_read((char *)line, &count, rrtp->p, BU_PROCESS_STDERR, 
RT_MAXLINE) <= 0) {
@@ -1329,7 +1321,7 @@
 
        /* Done watching for output, undo subprocess I/O hooks. */
        if (gedp->ged_delete_io_handler) {
-           (*gedp->ged_delete_io_handler)(gedp->ged_interp, rrtp->chan, 
rrtp->p, BU_PROCESS_STDERR);
+           (*gedp->ged_delete_io_handler)(rrtp, BU_PROCESS_STDERR);
        }
 
 
@@ -1350,7 +1342,6 @@
        /* free rrtp */
        BU_LIST_DEQUEUE(&rrtp->l);
        BU_PUT(rrtp, struct ged_subprocess);
-       BU_PUT(drcdp, struct _ged_rt_client_data);
 
        return;
     }
@@ -1432,7 +1423,6 @@
     FILE *fp_in;
     vect_t eye_model;
     struct ged_subprocess *run_rtp;
-    struct _ged_rt_client_data *drcdp;
     struct bu_process *p = NULL;
 
     bu_process_exec(&p, gd_rt_cmd[0], cmd_len, gd_rt_cmd, 0, 0);
@@ -1460,13 +1450,9 @@
     run_rtp->aborted = 0;
     run_rtp->gedp = gedp;
 
-    BU_GET(drcdp, struct _ged_rt_client_data);
-    drcdp->rrtp = run_rtp;
-    drcdp->u_data = gedp->ged_io_data;
-
     /* If we know how, set up hooks so the parent process knows to watch for 
output. */
     if (gedp->ged_create_io_handler) {
-       (*gedp->ged_create_io_handler)(&(run_rtp->chan), p, BU_PROCESS_STDERR, 
gedp->io_mode, (void *)drcdp, _ged_rt_output_handler);
+       (*gedp->ged_create_io_handler)(run_rtp, BU_PROCESS_STDERR, 
_ged_rt_output_handler, (void *)run_rtp);
     }
     return GED_OK;
 }

Modified: brlcad/branches/bioh/src/libged/rtcheck/rtcheck.c
===================================================================
--- brlcad/branches/bioh/src/libged/rtcheck/rtcheck.c   2020-07-31 16:00:56 UTC 
(rev 76612)
+++ brlcad/branches/bioh/src/libged/rtcheck/rtcheck.c   2020-07-31 19:18:16 UTC 
(rev 76613)
@@ -39,13 +39,11 @@
 
 struct ged_rtcheck {
     struct ged_subprocess *rrtp;
-    struct ged *gedp;
     FILE *fp;
     struct bn_vlblock *vbp;
     struct bu_list *vhead;
     double csize;
     void *chan;
-    struct bu_process *p;
     int read_failed;
     int draw_read_failed;
 };
@@ -54,24 +52,24 @@
 rtcheck_handler_cleanup(struct ged_rtcheck *rtcp)
 {
     int retcode;
+    struct ged_subprocess *rrtp = rtcp->rrtp;
+    struct ged *gedp = rrtp->gedp;
 
-    if (rtcp->gedp->ged_delete_io_handler) {
-       (*rtcp->gedp->ged_delete_io_handler)(rtcp->gedp->ged_interp, 
rtcp->rrtp->chan,
-               rtcp->rrtp->p, BU_PROCESS_STDOUT);
-       (*rtcp->gedp->ged_delete_io_handler)(rtcp->gedp->ged_interp, rtcp->chan,
-               rtcp->p, BU_PROCESS_STDERR);
+    if (gedp->ged_delete_io_handler) {
+       (*gedp->ged_delete_io_handler)(rrtp, BU_PROCESS_STDOUT);
+       (*gedp->ged_delete_io_handler)(rrtp, BU_PROCESS_STDERR);
     }
 
-    bu_process_close(rtcp->rrtp->p, BU_PROCESS_STDOUT);
+    bu_process_close(rrtp->p, BU_PROCESS_STDOUT);
 
     /* wait for the forked process */
-    retcode = bu_process_wait(NULL, rtcp->rrtp->p, 0);
+    retcode = bu_process_wait(NULL, rrtp->p, 0);
     if (retcode != 0) {
-       _ged_wait_status(rtcp->gedp->ged_result_str, retcode);
+       _ged_wait_status(gedp->ged_result_str, retcode);
     }
 
-    BU_LIST_DEQUEUE(&rtcp->rrtp->l);
-    BU_PUT(rtcp->rrtp, struct ged_subprocess);
+    BU_LIST_DEQUEUE(&rrtp->l);
+    BU_PUT(rrtp, struct ged_subprocess);
     BU_PUT(rtcp, struct ged_rtcheck);
 }
 
@@ -80,6 +78,8 @@
 {
     int value = 0;
     struct ged_rtcheck *rtcp = (struct ged_rtcheck *)clientData;
+    struct ged_subprocess *rrtp = rtcp->rrtp;
+    struct ged *gedp = rrtp->gedp;
 
     /* Get vector output from rtcheck */
     if (!rtcp->draw_read_failed && (feof(rtcp->fp) || (value = getc(rtcp->fp)) 
== EOF)) {
@@ -89,7 +89,7 @@
 
        rtcp->draw_read_failed = 1;
 
-       dl_set_flag(rtcp->gedp->ged_gdp->gd_headDisplay, DOWN);
+       dl_set_flag(gedp->ged_gdp->gd_headDisplay, DOWN);
 
        /* Add overlay (or, if nothing to draw, clear any stale overlay) */
        if (rtcp->vbp) {
@@ -102,7 +102,7 @@
        }
 
        if (have_visual) {
-           _ged_cvt_vlblock_to_solids(rtcp->gedp, rtcp->vbp, sname, 0);
+           _ged_cvt_vlblock_to_solids(gedp, rtcp->vbp, sname, 0);
            bn_vlblock_free(rtcp->vbp);
        } else {
            /* TODO - yuck.  This name is a product of the internals of the
@@ -112,8 +112,8 @@
             * current phony object drawing system.*/
            const char *sname_obj = "OVERLAPSffff00";
            struct directory *dp;
-           if ((dp = db_lookup(rtcp->gedp->ged_wdbp->dbip, sname_obj, 
LOOKUP_QUIET)) != RT_DIR_NULL) {
-               dl_erasePathFromDisplay(rtcp->gedp, sname_obj, 0);
+           if ((dp = db_lookup(gedp->ged_wdbp->dbip, sname_obj, LOOKUP_QUIET)) 
!= RT_DIR_NULL) {
+               dl_erasePathFromDisplay(gedp, sname_obj, 0);
            }
        }
 
@@ -131,7 +131,7 @@
                rtcp->fp,
                value,
                rtcp->csize,
-               rtcp->gedp->ged_gdp->gd_uplotOutputMode);
+               gedp->ged_gdp->gd_uplotOutputMode);
     }
 }
 
@@ -141,12 +141,14 @@
     int count;
     char line[RT_MAXLINE] = {0};
     struct ged_rtcheck *rtcp = (struct ged_rtcheck *)clientData;
+    struct ged_subprocess *rrtp = rtcp->rrtp;
+    struct ged *gedp = rrtp->gedp;
 
     /* Get textual output from rtcheck */
-    if (bu_process_read((char *)line, &count, rtcp->p, BU_PROCESS_STDERR, 
RT_MAXLINE) <= 0) {
+    if (bu_process_read((char *)line, &count, rrtp->p, BU_PROCESS_STDERR, 
RT_MAXLINE) <= 0) {
        rtcp->read_failed = 1;
-       if (rtcp->gedp->ged_gdp->gd_rtCmdNotify != (void (*)(int))0)
-           rtcp->gedp->ged_gdp->gd_rtCmdNotify(0);
+       if (gedp->ged_gdp->gd_rtCmdNotify != (void (*)(int))0)
+           gedp->ged_gdp->gd_rtCmdNotify(0);
     }
 
 
@@ -156,10 +158,10 @@
     }
 
     line[count] = '\0';
-    if (rtcp->gedp->ged_output_handler != (void (*)(struct ged *, char *))0) {
-       ged_output_handler_cb(rtcp->gedp, line);
+    if (gedp->ged_output_handler != (void (*)(struct ged *, char *))0) {
+       ged_output_handler_cb(gedp, line);
     }  else {
-       bu_vls_printf(rtcp->gedp->ged_result_str, "%s", line);
+       bu_vls_printf(gedp->ged_result_str, "%s", line);
     }
 }
 
@@ -253,7 +255,6 @@
 
     /* create the rtcheck struct */
     BU_GET(rtcp, struct ged_rtcheck);
-    rtcp->gedp = gedp;
     rtcp->fp = bu_process_open(p, BU_PROCESS_STDOUT);
     /* Needed on Windows for successful rtcheck drawing data communication */
     setmode(fileno(rtcp->fp), O_BINARY);
@@ -260,7 +261,6 @@
     rtcp->vbp = rt_vlblock_init();
     rtcp->vhead = bn_vlblock_find(rtcp->vbp, 0xFF, 0xFF, 0x00);
     rtcp->csize = gedp->ged_gvp->gv_scale * 0.01;
-    rtcp->p = p;
     rtcp->read_failed = 0;
     rtcp->draw_read_failed = 0;
 
@@ -270,13 +270,13 @@
     rtcp->rrtp->aborted = 0;
     rtcp->rrtp->gedp = gedp;
     if (gedp->ged_create_io_handler) {
-       (*gedp->ged_create_io_handler)(&(rtcp->rrtp->chan), p, 
BU_PROCESS_STDOUT, gedp->io_mode, (void *)rtcp, rtcheck_vector_handler);
+       (*gedp->ged_create_io_handler)(rtcp->rrtp, BU_PROCESS_STDOUT, 
rtcheck_vector_handler, (void *)rtcp);
     }
     BU_LIST_INIT(&rtcp->rrtp->l);
     BU_LIST_APPEND(&gedp->gd_headSubprocess.l, &rtcp->rrtp->l);
 
     if (gedp->ged_create_io_handler) {
-       (*gedp->ged_create_io_handler)(&(rtcp->chan), p, BU_PROCESS_STDERR, 
gedp->io_mode, (void *)rtcp, rtcheck_output_handler);
+       (*gedp->ged_create_io_handler)(rtcp->rrtp, BU_PROCESS_STDERR, 
rtcheck_output_handler, (void *)rtcp);
     }
 
     bu_free(gd_rt_cmd, "free gd_rt_cmd");

Modified: brlcad/branches/bioh/src/libged/rtwizard/rtwizard.c
===================================================================
--- brlcad/branches/bioh/src/libged/rtwizard/rtwizard.c 2020-07-31 16:00:56 UTC 
(rev 76612)
+++ brlcad/branches/bioh/src/libged/rtwizard/rtwizard.c 2020-07-31 19:18:16 UTC 
(rev 76613)
@@ -38,17 +38,10 @@
 
 #include "../ged_private.h"
 
-struct _ged_rt_client_data {
-    struct ged_subprocess *rrtp;
-    void *u_data;
-};
-
-
 int
 _ged_run_rtwizard(struct ged *gedp, int cmd_len, const char **gd_rt_cmd)
 {
     struct ged_subprocess *run_rtp;
-    struct _ged_rt_client_data *drcdp;
     struct bu_process *p;
 
     bu_process_exec(&p, gd_rt_cmd[0], cmd_len, (const char **)gd_rt_cmd, 0, 0);
@@ -70,13 +63,8 @@
     run_rtp->aborted = 0;
     run_rtp->gedp = gedp;
 
-    /* must be BU_GET() to match release in _ged_rt_output_handler */
-    BU_GET(drcdp, struct _ged_rt_client_data);
-    drcdp->rrtp = run_rtp;
-    drcdp->u_data = gedp->ged_io_data;
-
     if (gedp->ged_create_io_handler) {
-       (*gedp->ged_create_io_handler)(&(run_rtp->chan), p, BU_PROCESS_STDERR, 
gedp->io_mode, (void *)drcdp, _ged_rt_output_handler);
+       (*gedp->ged_create_io_handler)(run_rtp, BU_PROCESS_STDERR, 
_ged_rt_output_handler, (void *)run_rtp);
     }
 
     return GED_OK;

Modified: brlcad/branches/bioh/src/libtclcad/tclcad_obj.c
===================================================================
--- brlcad/branches/bioh/src/libtclcad/tclcad_obj.c     2020-07-31 16:00:56 UTC 
(rev 76612)
+++ brlcad/branches/bioh/src/libtclcad/tclcad_obj.c     2020-07-31 19:18:16 UTC 
(rev 76613)
@@ -1135,6 +1135,10 @@
            BU_PUT(tgd, struct tclcad_ged_data);
            top->to_gedp->u_data = NULL;
        }
+       if (top->to_gedp->ged_io_data) {
+           struct tclcad_io_data *t_iod = (struct tclcad_io_data 
*)top->to_gedp->ged_io_data;
+           BU_PUT(t_iod, struct tclcad_io_data);
+       }
 
        // Got the libtclcad cleanup done, have libged do its up.
        ged_close(top->to_gedp);
@@ -1176,20 +1180,19 @@
 /* Wrappers for setting up/tearing down IO handler */
 #ifndef _WIN32
 void
-tclcad_create_io_handler(void **UNUSED(chan), struct bu_process *p, int fd, 
int mode, void *data, ged_io_handler_callback_t callback)
+tclcad_create_io_handler(struct ged_subprocess *p, int fd, 
ged_io_handler_callback_t callback, void *data)
 {
-    int *fdp;
-    if (!p) return;
-    fdp = (int *)bu_process_fd(p, fd);
-    Tcl_CreateFileHandler(*fdp, mode, callback, (ClientData)data);
+    if (!p || !p->p || !p->gedp || !p->gedp->ged_io_data) return;
+    int *fdp = (int *)bu_process_fd(p->p, fd);
+    struct tclcad_io_data *t_iod = (struct tclcad_io_data 
*)p->gedp->ged_io_data;
+    Tcl_CreateFileHandler(*fdp, t_iod->io_mode, callback, (ClientData)data);
 }
 
 void
-tclcad_delete_io_handler(void *UNUSED(interp), void *UNUSED(chan), struct 
bu_process *p, int fd)
+tclcad_delete_io_handler(struct ged_subprocess *p, int fd)
 {
-    int *fdp;
     if (!p) return;
-    fdp = (int *)bu_process_fd(p, fd);
+    int *fdp = (int *)bu_process_fd(p->p, fd);
     Tcl_DeleteFileHandler(*fdp);
     close(*fdp);
 }
@@ -1196,25 +1199,23 @@
 
 #else
 void
-tclcad_create_io_handler(void **chan, struct bu_process *p, int fd, int mode, 
void *data, ged_io_handler_callback_t callback)
+tclcad_create_io_handler(struct ged_subprocess *p, int fd, 
ged_io_handler_callback_t callback, void *data)
 {
-    HANDLE *fdp;
-    if (!chan || !p) return;
-    fdp = (HANDLE *)bu_process_fd(p, fd);
-    (*chan) = (void *)Tcl_MakeFileChannel(*fdp, mode);
-    Tcl_CreateChannelHandler((Tcl_Channel)(*chan), mode, callback, 
(ClientData)data);
+    if (!p || !p->p || !p->gedp || !p->gedp->ged_io_data) return;
+    struct tclcad_io_data *t_iod = (struct tclcad_io_data 
*)p->gedp->ged_io_data;
+    HANDLE *fdp = (HANDLE *)bu_process_fd(p->p, fd);
+    (*t_iod->chan) = (void *)Tcl_MakeFileChannel(*fdp, t_iod->io_mode);
+    Tcl_CreateChannelHandler(*t_iod->chan, t_iod->io_mode, callback, 
(ClientData)data);
 }
 
 void
-tclcad_delete_io_handler(void *interp, void *chan, struct bu_process *p, int 
fd)
+tclcad_delete_io_handler(struct ged_subprocess *p, int fd)
 {
-    HANDLE *fdp;
-    Tcl_Interp *tcl_interp;
-    if (!chan || !p) return;
-    tcl_interp = (Tcl_Interp *)interp;
-    fdp = (HANDLE *)bu_process_fd(p, fd);
-    Tcl_DeleteChannelHandler((Tcl_Channel)chan, NULL, (ClientData)NULL);
-    Tcl_Close(tcl_interp, (Tcl_Channel)chan);
+    if (!p || !p->p || !p->p->gedp || !p->p->gedp->ged_io_data) return;
+    struct tclcad_io_data *t_iod = (struct tclcad_io_data 
*)p->gedp->ged_io_data;
+    HANDLE *fdp = (HANDLE *)bu_process_fd(p->p, fd);
+    Tcl_DeleteChannelHandler(t_oid->chan, NULL, (ClientData)NULL);
+    Tcl_Close(t_oid->interp, t_oid->chan);
 }
 #endif
 
@@ -1295,9 +1296,13 @@
     gedp->ged_interp = (void *)interp;
 
     /* Set the Tcl specific I/O handlers for asynchronous subprocess I/O */
+    struct tclcad_io_data *t_iod;
+    BU_GET(t_iod, struct tclcad_io_data);
+    t_iod->io_mode  = TCL_READABLE;
+    t_iod->interp = interp;
+    gedp->ged_io_data = (void *)t_iod;
     gedp->ged_create_io_handler = &tclcad_create_io_handler;
     gedp->ged_delete_io_handler = &tclcad_delete_io_handler;
-    gedp->io_mode = TCL_READABLE;
 
     /* initialize tclcad_obj */
     BU_ALLOC(top, struct tclcad_obj);

Modified: brlcad/branches/bioh/src/mged/setup.c
===================================================================
--- brlcad/branches/bioh/src/mged/setup.c       2020-07-31 16:00:56 UTC (rev 
76612)
+++ brlcad/branches/bioh/src/mged/setup.c       2020-07-31 19:18:16 UTC (rev 
76613)
@@ -476,10 +476,15 @@
     mged_global_variable_setup(*interpreter);
     mged_variable_setup(*interpreter);
     GEDP->ged_interp = (void *)*interpreter;
+    GEDP->ged_interp_eval = &mged_db_search_callback;
+
+    struct tclcad_io_data *t_iod;
+    BU_GET(t_iod, struct tclcad_io_data);
+    t_iod->io_mode = TCL_READABLE;
+    t_iod->interp = *interpreter;
+    GEDP->ged_io_data = t_iod;
     GEDP->ged_create_io_handler = &tclcad_create_io_handler;
     GEDP->ged_delete_io_handler = &tclcad_delete_io_handler;
-    GEDP->io_mode = TCL_READABLE;
-    GEDP->ged_interp_eval = &mged_db_search_callback;
 
     /* Tcl needs to write nulls onto subscripted variable names */
     bu_vls_printf(&str, "%s(state)", MGED_DISPLAY_VAR);

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
brlcad-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to