Changeset 387

Show
Ignore:
Timestamp:
05/17/07 16:25:27 (17 months ago)
Author:
krobillard
Message:

Thread safe Thune -

The only globals are now the static ur_global & ur_envGlobal.
Each thread has own data store.
Series data now accessed through functions which take thread pointer.
Word names now part of UrlanEnv? - no longer a binary!
Hold/release now implemented with a block.

Location:
branches/thune/thread_safe
Files:
26 modified

Legend:

Unmodified
Added
Removed
  • branches/thune/thread_safe/config.t

    r350 r387  
    11; Thune Configuration 
    22 
    3 [x] bzip2    "Include bzip2 compress/decompress calls" 
    4 [x] trig     "Include trigonometric math calls" 
    5 [x] math3d   "Include vector & matrix math calls" 
     3[ ] bzip2    "Include bzip2 compress/decompress calls" 
     4[ ] trig     "Include trigonometric math calls" 
     5[ ] math3d   "Include vector & matrix math calls" 
    66             enable trig 
    7 [x] dt-code  "Include 'code datatype" 
     7[ ] dt-code  "Include 'code datatype" 
    88 
    9 [x] net      "UDP socket port" 
     9[ ] net      "UDP socket port" 
    1010 
    1111[ ] uds      "Library with datatype & gc system only - no eval" 
  • branches/thune/thread_safe/console.c

    r369 r387  
    2121#include <assert.h> 
    2222#include <stdio.h> 
    23 #include "urlan.h" 
     23#include "env.h" 
    2424 
    2525 
     
    4040#else 
    4141 
    42 #define APPNAME     "Thune" 
     42#define APPNAME     "Bloc3" 
    4343#define CUSTOM_DT           0 
    4444#define CUSTOM_DT_COUNT     0 
     
    7777 
    7878 
    79 static void reportError( UThread* th ) 
     79static void reportError( UThread* ut ) 
    8080{ 
    8181    UString* str; 
    8282#if 0 
    8383    UCell* val; 
    84     val = ur_result( th, 0 ); 
     84    val = ur_result( ut, 0 ); 
    8585    str = ur_binPtr( val->err.strN ); 
    8686 
     
    8989            str->ptr.c ); 
    9090#else 
    91     str = ur_binPtr( th->callTempBinN ); 
     91    str = ur_threadTmp( ut ); 
    9292    str->used = 0; 
    93     ur_toStr( ur_result(th, 0), str, 0 ); 
     93    ur_toStr( ur_result(ut, 0), str, 0 ); 
    9494    ur_termCStr( str ); 
    9595    printf( str->ptr.c ); 
    9696#endif 
    9797 
    98     //ur_threadReset( th ); 
     98    //ur_threadReset( ut ); 
    9999} 
    100100 
     
    132132    } 
    133133#endif 
     134 
     135    ur_freezeEnv( env.threads, 128, 256 ); 
    134136 
    135137    if( argc > 1 ) 
     
    255257 
    256258                        ur_arrayInit( &str, 1, 0 ); 
    257                         ur_toStr( val, &str, 0 ); 
     259                        ur_toStrT( env.threads, val, &str, 0 ); 
    258260                        if( str.ptr.c ) 
    259261                        { 
  • branches/thune/thread_safe/context.c

    r323 r387  
    11/*============================================================================ 
    22    Thune Interpreter 
    3     Copyright (C) 2005-2006  Karl Robillard 
     3    Copyright (C) 2005-2007  Karl Robillard 
    44 
    55    This library is free software; you can redistribute it and/or 
     
    1919 
    2020 
    21 #include "os.h" 
    22 #include "urlan.h" 
    2321#include "internal.h" 
    2422 
     
    3230  Appends atom name to string. 
    3331*/ 
    34 void ur_atomStr( UAtom atom, UString* str ) 
    35 { 
    36     UBinary* names; 
    37     AtomRec* rec; 
    38  
    39     rec = ((AtomRec*) ur_env->atoms.ptr.v) + atom; 
    40     names = ur_binPtr( BIN_ATOM_NAMES ); 
     32void ur_atomStrT( UThread* ut, UAtom atom, UString* str ) 
     33{ 
     34    AtomRec* rec = ((AtomRec*) ut->env->atoms.ptr.v) + atom; 
    4135 
    4236    ur_arrayReserve( str, sizeof(char), str->used + rec->nameLen ); 
    4337    memCpy( str->ptr.c + str->used, 
    44             names->ptr.c + rec->nameIndex, 
     38            ut->env->atomNames.ptr.c + rec->nameIndex, 
    4539            rec->nameLen ); 
    4640    str->used += rec->nameLen; 
     
    5448 
    5549 
    56 const char* ur_atomCStr( UAtom atom, int* plen ) 
    57 { 
    58     UBinary* names; 
    59     AtomRec* rec; 
    60  
    61     rec = ((AtomRec*) ur_env->atoms.ptr.v) + atom; 
    62     names = ur_binPtr( BIN_ATOM_NAMES ); 
     50const char* ur_atomCStrT( UThread* ut, UAtom atom, int* plen ) 
     51{ 
     52    AtomRec* rec = ((AtomRec*) ut->env->atoms.ptr.v) + atom; 
    6353    if( plen ) 
    6454        *plen = rec->nameLen; 
    65     return names->ptr.c + rec->nameIndex; 
     55    return ut->env->atomNames.ptr.c + rec->nameIndex; 
    6656} 
    6757 
     
    128118 
    129119#ifdef DEBUG 
    130 void dumpAtoms() 
    131 { 
    132     UString* names; 
    133     AtomRec* table = (AtomRec*) ur_env->atoms.ptr.v; 
     120void dumpAtoms( UThread* ut ) 
     121{ 
     122    LOCK_GLOBAL 
     123    { 
     124    const char* names = ut->env->atomNames.ptr.c; 
     125    AtomRec* table = (AtomRec*) ut->env->atoms.ptr.v; 
    134126    AtomRec* it  = table; 
    135     AtomRec* end = table + ur_env->atoms.used; 
    136  
    137     names = ur_binPtr( BIN_ATOM_NAMES ); 
     127    AtomRec* end = table + ut->env->atoms.used; 
    138128 
    139129    while( it != end ) 
     
    141131        dprint( "%4ld %08x %5d %5d %s\n", it - table, it->hash, 
    142132                it->head, it->chain, 
    143                 names->ptr.c + it->nameIndex ); 
     133                names + it->nameIndex ); 
    144134        ++it; 
    145135    } 
    146136 
    147     end = table + ur_env->atoms.avail; 
     137    end = table + ut->env->atoms.avail; 
    148138    while( it != end ) 
    149139    { 
     
    152142        ++it; 
    153143    } 
     144    } 
     145    UNLOCK_GLOBAL 
    154146} 
    155147#endif 
     
    159151  Add atom to environment. 
    160152 
     153  If the environment has multiple threads, the caller must have called 
     154  LOCK_GLOBAL. 
     155 
    161156  \param str  Name of atom. 
    162157  \param len  Number of characters. 
     
    164159  \returns Atom  
    165160*/ 
    166 UAtom ur_intern( UrlanEnv* env, const char* str, int len ) 
     161UAtom ur_internT( UThread* ut, const char* str, int len ) 
    167162{ 
    168163    char* cp; 
     
    182177    // Check if atom already exists. 
    183178 
    184     atoms = &env->atoms; 
     179    atoms = &ut->env->atoms; 
    185180    table = (AtomRec*) atoms->ptr.v; 
    186     names = ur_binPtr( BIN_ATOM_NAMES ); 
     181    names = &ut->env->atomNames; 
    187182 
    188183    hash = ur_hash( str, str + len ); 
     
    233228    // Nope, add new atom. 
    234229 
     230    /* TODO: Make atoms & atomNames thread safe through one of the following: 
     231 
     232       1. Halt all other threads. 
     233       2. Fix size of atom arrays and throw error/assert when full. 
     234       3. Use LOCK_GLOBAL in or around these functions in addition to ur_intern: 
     235            ur_atomStrT() 
     236            ur_atomCStrT() 
     237            dumpAtoms() 
     238    */ 
     239 
    235240    if( atoms->used == atoms->avail ) 
    236241    { 
     
    275280  \returns  Index of word in context. 
    276281*/ 
    277 int ur_internWord( const UContext* ctx, UAtom atom ) 
     282int ur_internWordT( UThread* ut, const UContext* ctx, UAtom atom ) 
    278283{ 
    279284    int wrdN; 
     
    421426  \returns  Word index or -1 if not found. 
    422427*/ 
    423 int ur_lookup( const UContext* ctx, UAtom atom ) 
     428int ur_lookupT( UThread* ut, const UContext* ctx, UAtom atom ) 
    424429{ 
    425430    UBlock* wblk; 
     
    454459// Atom remains the same. 
    455460 
    456 #define _bindWord(val) \ 
    457     wrdN = ur_lookup( ctx, val->word.atom ); \ 
     461#define _bindWord(cell) \ 
     462    wrdN = ur_lookup( ctx, cell->word.atom ); \ 
    458463    if( wrdN > -1 ) { \ 
    459         val->word.wordBlk = ctx->ctx.wordBlk; \ 
    460         val->word.valBlk  = ctx->ctx.valBlk; \ 
    461         val->word.index   = wrdN; } 
    462  
    463  
    464 UBlock* ur_bind( UIndex blkN, UContext* ctx ) 
     464        if( ur_bindType(cell) != btype ) \ 
     465            ur_setBindType(cell,btype); \ 
     466        cell->word.wordBlk = ctx->ctx.wordBlk; \ 
     467        cell->word.valBlk  = ctx->ctx.valBlk; \ 
     468        cell->word.index   = wrdN; } 
     469 
     470 
     471UBlock* ur_bindT( UThread* ut, UIndex blkN, const UContext* ctx, int btype ) 
    465472{ 
    466473    int wrdN; 
     
    469476    UCell* end = it + blk->used; 
    470477 
     478    if( ur_isGlobal(blkN) ) 
     479        return 0;       // Cannot bind global blocks. 
     480 
    471481    while( it != end ) 
    472482    { 
    473         if( ur_isAWord(it) || 
    474             ur_is(it, UT_OPCODE) || 
    475             ur_is(it, UT_SELECT) || 
    476             ur_is(it, UT_SETSELECT) ) 
    477         { 
    478             _bindWord( it ); 
    479         } 
    480         else if( ur_is(it, UT_PATH) || ur_is(it, UT_SETPATH) ) 
    481         { 
    482             UCell* path1 = ur_blockPtr( it->series.n )->ptr.cells; 
    483             if( ur_isAWord(path1) ) 
    484             { 
    485                 _bindWord( path1 ); 
    486             } 
    487         } 
    488         else if( ur_is(it, UT_BLOCK) || ur_is(it, UT_PAREN) ) 
    489         { 
    490             ur_bind( it->series.n, ctx ); 
    491         } 
    492         else if( ur_is(it, UT_FUNCTION) ) 
    493         { 
    494             ur_bind( it->func.bodyN, ctx ); 
    495  
    496             // NOTE: Will probably need to rebind to local func context in 
    497             // case ctx contains the same words.  
    498             //orBind( orBlockPtr( it->func.bodyBlk ), it->func.context ); 
    499         } 
    500  
    501         ++it; 
    502     } 
    503  
    504     return blk; 
    505 } 
    506  
    507  
    508 #ifndef UR_CONFIG_UDS 
    509 /** 
    510   ur_resolveArgPath is provided as a fast but still convenient method of 
    511   resolving paths from C code. 
    512  
    513   Pass a number of datatype/value argument pairs terminated by UT_NONE to 
    514   specify the path. A pair can be either UT_WORD,atom or UT_INT,int. 
    515  
    516   Returns zero if the path is not valid. 
    517  
    518   Using a string argument rather than a tag list would be more convenient 
    519   but not as quick. 
    520 */ 
    521 UCell* ur_resolveArgPath( int first_tag, ... ) 
    522 { 
    523     va_list args; 
    524     int tag; 
    525     int data; 
    526     UIndex wrd; 
    527     UBlock* blk; 
    528     UCell* val; 
    529  
    530     val = &ur_global; 
    531  
    532     va_start(args, first_tag); 
    533     tag = first_tag; 
    534  
    535     while( tag != UT_NONE ) 
    536     { 
    537         data = va_arg(args, int); 
    538         switch( tag ) 
     483        switch( ur_type(it) ) 
    539484        { 
    540485            case UT_WORD: 
    541                 if( ur_is(val, UT_CONTEXT) ) 
     486            case UT_SETWORD: 
     487            case UT_GETWORD: 
     488            case UT_LITWORD: 
     489            case UT_SELECT: 
     490            case UT_SETSELECT: 
     491            case UT_OPCODE: 
     492                _bindWord( it ); 
     493                break; 
     494 
     495            case UT_PATH: 
     496            case UT_SETPATH: 
     497            { 
     498                UCell* path1 = ur_blockPtr( it->series.n )->ptr.cells; 
     499                if( ur_isAWord(path1) ) 
    542500                { 
    543                     wrd = ur_lookup( val, data ); 
    544                     if( wrd < 0 ) 
    545                         goto abort; 
    546  
    547                     blk = ur_blockPtr( val->ctx.valBlk ); 
    548                     val = blk->ptr.cells + wrd; 
    549                     break; 
     501                    _bindWord( path1 ); 
    550502                } 
    551                 goto abort; 
    552  
    553             case UT_INT: 
    554                 if( ur_is(val, UT_BLOCK) ) 
    555                 { 
    556                     blk = ur_block(val); 
    557                     val = blk->ptr.cells + data; 
    558                     break; 
    559                 } 
    560                 // TODO: binary, string, etc 
    561                 goto abort; 
    562  
    563             default: 
    564                 goto abort; 
     503            } 
     504                break; 
     505 
     506            case UT_BLOCK: 
     507            case UT_PAREN: 
     508                ur_bindT( ut, it->series.n, ctx, btype ); 
     509                break; 
     510 
     511            case UT_FUNCTION: 
     512                ur_bindT( ut, it->func.bodyN, ctx, btype ); 
     513 
     514                // NOTE: Will probably need to rebind to local func context in 
     515                // case ctx contains the same words.  
     516                //orBind( orBlockPtr( it->func.bodyBlk ), it->func.context ); 
     517                break; 
    565518        } 
    566         tag = va_arg(args, int); 
    567     } 
    568  
    569 done: 
    570  
    571     va_end(args); 
    572     return val; 
    573  
    574 abort: 
    575  
    576     val = 0; 
    577     goto done; 
    578 } 
    579 #endif 
     519 
     520        ++it; 
     521    } 
     522 
     523    return blk; 
     524} 
    580525 
    581526 
  • branches/thune/thread_safe/encoding.c

    r274 r387  
    7676    res = UR_TOS; 
    7777 
    78     if( ur_isAWord(tos) && ur_stringSlice(res, &cpA, &cpB) ) 
     78    if( ur_isAWord(tos) && ur_stringSlice(ut, res, &cpA, &cpB) ) 
    7979    { 
    8080        count = cpB - cpA; 
  • branches/thune/thread_safe/eval.c

    r385 r387  
    1919 
    2020 
    21 #include "os.h" 
    22 #include "urlan.h" 
     21#include "internal.h" 
    2322#include "urlan_atoms.h" 
    24 #include "internal.h" 
    2523#include "bignum.h" 
    2624 
    2725 
     26extern UContext ur_global; 
     27extern UContext ur_envGlobal; 
     28 
    2829extern void uc_console_out( UThread*, UCell* ); 
    2930 
    3031 
    3132#ifdef DEBUG 
    32 void ur_dumpBlock( UIndex blkN ) 
     33void ur_dumpBlock( UThread* ut, UIndex blkN ) 
    3334{ 
    3435    UCell* cell; 
     
    5859 
    5960 
    60 static void _infuseOpcodes( UThread* thr, UIndex blkN ) 
     61static void _infuseOpcodes( UThread* ut, UIndex blkN ) 
    6162{ 
    6263    UBlock* blk; 
    63     UBlock* gblk; 
     64    UContext* global; 
    6465    const UCell* ctx; 
    6566    int wrdN; 
    6667 
    67     blk = ur_bind( blkN, &ur_global ); 
    68  
    69     wrdN = ur_lookup( &ur_global, UR_ATOM_KERNEL_OPS ); 
    70     //assert( wrdN > -1 ); 
    71     if( wrdN > -1 ) 
    72     { 
    73         gblk = ur_blockPtr( GLOBAL_VAL_BLKN ); 
    74         ctx = gblk->ptr.cells + wrdN; 
    75  
    76         assert( ctx->id.type == UT_CONTEXT ); 
    77  
    78         ur_infuse( thr, blk, ctx ); 
     68    global = (ut->env->blocks.arr.used) ? &ur_envGlobal : &ur_global; 
     69 
     70    wrdN = ur_lookup( global, UR_ATOM_KERNEL_OPS ); 
     71    assert( wrdN > -1 ); 
     72    //if( wrdN > -1 ) 
     73    { 
     74        blk = ur_blockPtr( global->ctx.valBlk ); 
     75        ctx = blk->ptr.cells + wrdN; 
     76 
     77        assert( ur_is(ctx, UT_CONTEXT) ); 
     78 
     79        blk = ur_blockPtr( blkN ); 
     80        ur_infuse( ut, blk, ctx ); 
    7981    } 
    8082} 
     
    8688   returned. 
    8789*/ 
    88 static int ur_itLen( UCell* cell ) 
     90static int ur_itLen( UThread* ut, UCell* cell ) 
    8991{ 
    9092    int len = ur_seriesLen( cell ); 
     
    101103  Res may be the same as sel. 
    102104*/ 
    103 int ur_getSelector( UThread* ur_thread, const UCell* sel, UCell* res ) 
     105int ur_getSelector( UThread* ut, const UCell* sel, UCell* res ) 
    104106{ 
    105107#define ATOM_OFF(val,atm)   (((unsigned int) val) - atm) 
     
    107109    UCell* val; 
    108110 
    109     val = ur_wordCell( ur_thread, sel ); 
     111    val = ur_wordCell( ut, sel ); 
    110112    if( ! val ) 
    111113        return 0; 
     
    157159                if( ur_type(val) >= UT_BI_COUNT ) 
    158160                { 
    159                     UDatatypeSelFunc func = ur_thread->env->customDT 
     161                    UDatatypeSelFunc func = ut->env->customDT 
    160162                                [ ur_type(val) - UT_BI_COUNT ].selectAtom; 
    161163                    if( func ) 
    162                         return func( ur_thread, val, sel, res ); 
     164                        return func( ut, val, sel, res ); 
    163165                } 
    164166                goto set_none; 
     
    167169    else 
    168170    { 
    169         if( ur_pick( val, ur_sel(sel) - 1, res ) ) 
     171        if( ur_pick( ut, val, ur_sel(sel) - 1, res ) ) 
    170172            return 1; 
    171173    } 
    172174 
    173     ur_throwErr( ur_thread, UR_EX_SCRIPT, "Invalid select!" ); 
     175    ur_throwErr( UR_ERR_SCRIPT, "Invalid select!" ); 
    174176    return 0; 
    175177 
     
    184186  Returns non-zero if successful. 
    185187*/ 
    186 int ur_setSelector( UThread* ur_thread, const UCell* sel, const UCell* nval ) 
     188int ur_setSelector( UThread* ut, const UCell* sel, const UCell* nval ) 
    187189{ 
    188190    UBlock* blk; 
    189191    UCell* val; 
    190192 
    191     val = ur_wordCell( ur_thread, sel ); 
     193    val = ur_wordCell( ut, sel ); 
    192194    if( ! val ) 
    193195        return 0; 
     
    242244            if( ! ur_selIsAtom(sel) ) 
    243245            { 
    244                 if( ur_poke( val, ur_sel(sel) - 1, nval ) ) 
    245                     return 1; 
    246             } 
    247             break; 
    248     } 
    249  
    250     ur_throwErr( ur_thread, UR_EX_SCRIPT, "Invalid select!" ); 
     246                if( ur_poke( ut, val, ur_sel(sel) - 1, nval ) ) 
     247                    return 1; 
     248            } 
     249            break; 
     250    } 
     251 
     252    ur_throwErr( UR_ERR_SCRIPT, "Invalid select!" ); 
    251253    return 0; 
    252254} 
     
    283285    { 
    284286        UCell* val; 
    285         val = ur_wordCell( ur_thread, tos ); 
     287        val = ur_wordCell( ut, tos ); 
    286288        if( val ) 
    287289        { 
     
    317319 
    318320 
    319 static void _appendTraceBlk( UCellError* err, int n, int it ) 
     321static void _appendTraceBlk( UThread* ut, UCellError* err, int n, int it ) 
    320322{ 
    321323    if( err->traceBlk ) 
     
    334336#define _throwUnbound(th,cell)  _throwUnsetF(th,cell,"unbound") 
    335337 
    336 static void _throwUnsetF( UThread* ur_thread, const UCell* wcell, 
    337                           const char* umsg ) 
     338static void _throwUnsetF( UThread* ut, const UCell* wcell, const char* umsg ) 
    338339{ 
    339340    UString* str; 
    340     str = ur_binPtr( ur_thread->callTempBinN ); 
     341    str = ur_threadTmp( ut ); 
    341342    str->used = 0; 
    342343    ur_atomStr( ur_atom(wcell), str ); 
    343344    ur_termCStr( str ); 
    344     ur_throwErr( ur_thread, UR_EX_SCRIPT, 
    345                  "word '%s is %s", str->ptr.c, umsg ); 
    346 } 
    347  
    348  
    349 /* 
     345    ur_throwErr( UR_ERR_SCRIPT, "word '%s is %s", str->ptr.c, umsg ); 
     346} 
     347 
     348 
     349/** 
    350350   Returns cell pointer or zero if word does not reference a valid cell. 
    351351*/ 
    352 UCell* ur_wordCell( UThread* ur_thread, const UCell* pc ) 
    353 { 
    354     UCell* val; 
    355     int i; 
    356     
    357     i = pc->word.valBlk; 
    358     if( i < 0 ) 
    359     { 
    360         // Find function local frame i. 
    361  
    362         LocalFrame* it; 
    363         LocalFrame* end; 
    364  
    365         it  = UR_LF_BEG; 
    366         end = UR_LF_END; 
    367         while( it != end ) 
    368         { 
    369             if( it->localFrame.n == i ) 
    370             { 
    371                 val = it->localFrame.cell; 
    372               &nbs