You are here

Multi-Threaded use of Tcl Interpreters

admin의 아바타

출처: http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/661a10...

Tcl 인터프리터를 멀티 쓰레드로 돌리는 간단한 예입니다.

#include <pthread.h>
#include <iostream>
#include <vector>
#include <tcl.h>
using namespace std;
vector<Tcl_Interp*> interpreters;
const char* tcl_proc = "proc foo { } {\n"
                       "  set log [ open logfile a ]\n"
                       "  puts $log \"thread started\"\n"
//                       "  close $log\n"
                       "  return 3.4\n"
                       "}\n"
                       "foo\n"
                       "\n";
void* create_a_task_handler( void* slot_p ) {
    unsigned long slot_index = *((unsigned long*)slot_p);
    Tcl_Interp *interp = interpreters[slot_index] =
Tcl_CreateInterp();
    cout << "Executing " << slot_index << endl;
    int rc = Tcl_Eval( interp, tcl_proc );
    if ( rc != TCL_OK ) {
        cout << "An error was encountered during evaluation of TCL
code."
;
        const char * errorInfoStr  = Tcl_GetVar(interp, "errorInfo",
TCL_GLOBAL_ONLY);
        if ( errorInfoStr ) cout << errorInfoStr << endl;
    }
    Tcl_Obj *res = Tcl_GetObjResult( interp );
    double ret_val;
    rc = Tcl_GetDoubleFromObj(interp, res, &ret_val );
    cout << "Proc returned " << ret_val << endl;
    // Everything is fine if we delete the interpreters in the same
thread they were created in.
    //Tcl_DeleteInterp( interpreters[slot_index] );
    //interpreters[slot_index] = NULL;
    return NULL;
}

main( int argc, const char** argv ) {
    const char* usage = "Usage: tcl_mt [<thread_count> ]\n
thread_count is {1 2 4 8 or 16}\n\n"
;
    const int MAX_THREADS=16;
    int thread_count=1;
    if ( argc>1 ) {
        thread_count=atoi(argv[1]);
    }
    if ( thread_count != 1 && thread_count != 2 && thread_count != 4
&& thread_count != 8 && thread_count != 16 )
    {
        cout << "thread count must be 2,4,8 or 16." << endl;
        cout << usage << endl;
        exit(1);
    }
    pthread_t threads[MAX_THREADS];
    unsigned long slots[MAX_THREADS];
    interpreters.assign(thread_count, NULL);
    if ( argc == 1 ) {
        cout << "Running tasks in main thread." << endl;
        // straight ahead - no threads.
        slots[0] = 0;
        create_a_task_handler( &slots[0] );
        Tcl_DeleteInterp( interpreters[0] );
    } else {
        cout << "Running " << thread_count << " threads." << endl;
        for( unsigned long i=0; i != thread_count; ++i ) {
            slots[i] = i;
            pthread_create( &(threads[i]), NULL,
create_a_task_handler, &slots[i] );
        }
        for( unsigned long i=0; i != thread_count; ++i ) {
            pthread_join( threads[i], NULL );
        }
        for( unsigned long i=0; i != thread_count; ++i ) {
            if ( interpreters[i] ) {
                Tcl_DeleteInterp( interpreters[i] );
            }
        }
    }
}

For single threaded execution:
tcl_mt
Running tasks in main thread.
Executing 0
Proc returned 3.4

this works fine,

now for multi-threaded execution:

tcl_mt 2

Running 2 threads.
Executing 0
Executing 1
Proc returned 3.4
Proc returned 3.4
FlushChannel: damaged channel list
Aborted

포럼: