Show
Ignore:
Timestamp:
05/17/07 16:25:27 (18 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.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • 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