2014-06-18 47 views
0

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

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] 
} 

当我尝试这个我得到的“找不到矢量”,这是我在向量无法找到或出现错误时所放置的打印语句,是否有另一种方法来做到这一点,或者我错过了什么?

+0

'tsv :: set'是C语法错误。你的意思是C++吗? – wildplasser

回答

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 s的列表Tcl_Obj。这是BLT第一次创建时不可用的机制,它可能会比您期望的性能更好。 或者如果值的数量很大,并且您只需要传递它们和/或将它们存储起来,则发送大量的二进制文件(如果需要,binary scan命令将能够选取比特)。

相关的API将是Tcl_NewListObj,Tcl_NewDoubleObjTcl_NewByteArrayObj

相关问题