Changeset 387 for branches/thune/thread_safe/context.c
- Timestamp:
- 05/17/07 16:25:27 (18 months ago)
- Files:
-
- 1 modified
-
branches/thune/thread_safe/context.c (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/thune/thread_safe/context.c
r323 r387 1 1 /*============================================================================ 2 2 Thune Interpreter 3 Copyright (C) 2005-200 6Karl Robillard3 Copyright (C) 2005-2007 Karl Robillard 4 4 5 5 This library is free software; you can redistribute it and/or … … 19 19 20 20 21 #include "os.h"22 #include "urlan.h"23 21 #include "internal.h" 24 22 … … 32 30 Appends atom name to string. 33 31 */ 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 ); 32 void ur_atomStrT( UThread* ut, UAtom atom, UString* str ) 33 { 34 AtomRec* rec = ((AtomRec*) ut->env->atoms.ptr.v) + atom; 41 35 42 36 ur_arrayReserve( str, sizeof(char), str->used + rec->nameLen ); 43 37 memCpy( str->ptr.c + str->used, 44 names->ptr.c + rec->nameIndex,38 ut->env->atomNames.ptr.c + rec->nameIndex, 45 39 rec->nameLen ); 46 40 str->used += rec->nameLen; … … 54 48 55 49 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 ); 50 const char* ur_atomCStrT( UThread* ut, UAtom atom, int* plen ) 51 { 52 AtomRec* rec = ((AtomRec*) ut->env->atoms.ptr.v) + atom; 63 53 if( plen ) 64 54 *plen = rec->nameLen; 65 return names->ptr.c + rec->nameIndex;55 return ut->env->atomNames.ptr.c + rec->nameIndex; 66 56 } 67 57 … … 128 118 129 119 #ifdef DEBUG 130 void dumpAtoms() 131 { 132 UString* names; 133 AtomRec* table = (AtomRec*) ur_env->atoms.ptr.v; 120 void 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; 134 126 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; 138 128 139 129 while( it != end ) … … 141 131 dprint( "%4ld %08x %5d %5d %s\n", it - table, it->hash, 142 132 it->head, it->chain, 143 names ->ptr.c+ it->nameIndex );133 names + it->nameIndex ); 144 134 ++it; 145 135 } 146 136 147 end = table + u r_env->atoms.avail;137 end = table + ut->env->atoms.avail; 148 138 while( it != end ) 149 139 { … … 152 142 ++it; 153 143 } 144 } 145 UNLOCK_GLOBAL 154 146 } 155 147 #endif … … 159 151 Add atom to environment. 160 152 153 If the environment has multiple threads, the caller must have called 154 LOCK_GLOBAL. 155 161 156 \param str Name of atom. 162 157 \param len Number of characters. … … 164 159 \returns Atom 165 160 */ 166 UAtom ur_intern ( UrlanEnv* env, const char* str, int len )161 UAtom ur_internT( UThread* ut, const char* str, int len ) 167 162 { 168 163 char* cp; … … 182 177 // Check if atom already exists. 183 178 184 atoms = & env->atoms;179 atoms = &ut->env->atoms; 185 180 table = (AtomRec*) atoms->ptr.v; 186 names = ur_binPtr( BIN_ATOM_NAMES );181 names = &ut->env->atomNames; 187 182 188 183 hash = ur_hash( str, str + len ); … … 233 228 // Nope, add new atom. 234 229 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 235 240 if( atoms->used == atoms->avail ) 236 241 { … … 275 280 \returns Index of word in context. 276 281 */ 277 int ur_internWord (const UContext* ctx, UAtom atom )282 int ur_internWordT( UThread* ut, const UContext* ctx, UAtom atom ) 278 283 { 279 284 int wrdN; … … 421 426 \returns Word index or -1 if not found. 422 427 */ 423 int ur_lookup (const UContext* ctx, UAtom atom )428 int ur_lookupT( UThread* ut, const UContext* ctx, UAtom atom ) 424 429 { 425 430 UBlock* wblk; … … 454 459 // Atom remains the same. 455 460 456 #define _bindWord( val) \457 wrdN = ur_lookup( ctx, val->word.atom ); \461 #define _bindWord(cell) \ 462 wrdN = ur_lookup( ctx, cell->word.atom ); \ 458 463 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 471 UBlock* ur_bindT( UThread* ut, UIndex blkN, const UContext* ctx, int btype ) 465 472 { 466 473 int wrdN; … … 469 476 UCell* end = it + blk->used; 470 477 478 if( ur_isGlobal(blkN) ) 479 return 0; // Cannot bind global blocks. 480 471 481 while( it != end ) 472 482 { 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) ) 539 484 { 540 485 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) ) 542 500 { 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 ); 550 502 } 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; 565 518 } 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 } 580 525 581 526
