如何在单独的线程中传递blt向量

时间:2014-06-18 18:45:55

标签: c multithreading tcl

我有这个函数调用数据库,我正在使用C和tcl / tk所以这个函数的tcl调用在C中执行,但是当发生这种情况时,tcl中的系统挂起它处理查询的时间调用以及它填充向量的时间,我希望tcl应用程序继续工作并将此进程放在一个单独的线程中。这就是我现在正在尝试的。

处理数据库调用并填充向量的C函数:

static int getEpochPrototype(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]){
    Tcl_Obj *result;
    char sampleid[15];
    char tclxVec[15];
    char tclyVec[15];
    int length;
    int numResults;
    int i;
    Blt_Vector *xCVec, *yCVec;

    if (objc != 4) {
        Tcl_WrongNumArgs(interp, 3, objv, "number of argument error");
        return TCL_ERROR;
    }

    strcpy(sampleid,Tcl_GetStringFromObj(objv[1], &length));
    strcpy(tclxVec,Tcl_GetStringFromObj(objv[2], &length));
    strcpy(tclyVec,Tcl_GetStringFromObj(objv[3], &length));

    if (Blt_VectorExists(interp, tclxVec) != TCL_OK || Blt_VectorExists(interp, tclyVec) != TCL_OK) {
        if ((Blt_GetVector(interp, tclxVec, &xCVec) != TCL_OK) || (Blt_GetVector(interp, tclyVec, &yCVec) != TCL_OK)) {
            return TCL_ERROR;
        }
    } else {
           printf("Vector not found \n");
           return TCL_ERROR;
    }

    char command[256];
    PQclear(res);

    strcpy(command, "select extract ('epoch' from \"Timestamp\"), \"BioAccumulated\" from \"Results\" where \"SampleID\" = '");
    strcat(command, sampleid);
    strcat(command, "' order by \"Timestamp\" asc");
    res = PQexec(conn,command);
    numResults = PQntuples(res);
    double x[numResults], y[numResults];

    for (i = 0; i < numResults; i++)
    {   
        x[i] = strtod(PQgetvalue(res,i,0), NULL);
        y[i] = strtod(PQgetvalue(res,i,1), NULL);

    }

    /* Put the data into BLT vectors */
    if ((Blt_ResetVector(xCVec, x, numResults, numResults, TCL_VOLATILE) != TCL_OK) || (Blt_ResetVector(yCVec, y, numResults, numResults, TCL_VOLATILE) != TCL_OK)) {
        return TCL_ERROR;
    }


   return TCL_OK;
}

TCL函数尝试将blt向量发送到c线程:

blt::vector create xVec
blt::vector create yVec

tsv::set graph xtemp_shared xVec
tsv::set graph yBio_shared yVec

thread::create {
    load ./samples.so
    connectDB2

    #puts  "[tsv::get details sampleid_shared]"
    getEpochPrototype [tsv::get details sampleid_shared] [tsv::get graph xtemp_shared] [tsv::get graph yBio_shared]
}

当我尝试这个时,我得到了“找不到矢量”,这是我在找到矢量时出现的打印语句或者有错误,是否有其他方法可以做到或者我错过了什么?

1 个答案:

答案 0 :(得分:0)

Tcl的threading model要求您从创建该解释器的线程访问Tcl解释器的任何特定实例。 (Tcl的实现广泛使用特定于线程的数据。)你可以从另一个线程填充那些C数组 - 那里通常的C并行规则 - 然后使用Tcl_ThreadQueueEvent告诉另一个线程你有东西可以做;您发送的邮件实际上是代码+数据。

struct DoneReadingIntoArraysEvent {
    Tcl_Event eventHeader;
    Tcl_Interp *interp;
    double *x, *y;
    int length;
}

struct DoneReadingIntoArraysEvent callback;
callback.eventHeader.proc = &MyCallbackFunc;
callback.interp = theInterpHandleInTheOtherThread;
callback.x = x;
callback.y = y;
callback.length = numberOfValuesInArray;
Tcl_ThreadQueueEvent(mainThreadId, &callback.eventHeader, TCL_QUEUE_TAIL);

现在,在MyCallbackFunc中,您将Tcl_Event*参数转换回struct DoneReadingIntoArraysEvent(安全;它是第一个成员!)并检索您需要告诉解释器的值(和有问题的翻译。)

为了将值实际存入Tcl,我强烈 考虑使用包含一大堆双Tcl_Obj的列表Tcl_Obj。这是一种在首次创建BLT时不可用的机制,它可能具有比您期望的更好的性能。 或者,如果值的数量很大并且您只需要传递它们和/或存储它们,请发送一大块二进制文件(binary scan命令将能够在需要时选择位)。

相关API包括Tcl_NewListObjTcl_NewDoubleObjTcl_NewByteArrayObj