Annotation of researchv10no/cmd/cfront/libC/new/_arr_map.c, revision 1.1.1.1

1.1       root        1: /*ident        "@(#)C++env:lib/new/_arr_map.c  1.3" */
                      2: /**************************************************************************
                      3:                         Copyright (c) 1984 AT&T
                      4:                           All Rights Reserved   
                      5: 
                      6:         THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
                      7:       
                      8:         The copyright notice above does not evidence any        
                      9:         actual or intended publication of such source code.
                     10: 
                     11: *****************************************************************************/
                     12: 
                     13: 
                     14: // manage the global table of array pointers and counts
                     15: #include <values.h>
                     16: #include <new.h>
                     17: 
                     18: // !!!!  only works if sizeof(long) >= sizeof(void*)  !!!!
                     19: 
                     20: typedef void*  KEYTYP; // generic array address
                     21: void   __insert_new_array(KEYTYP key, int count);
                     22:        // key is a pointer to a new array.  It must
                     23:        //      be non-zero
                     24:        //      not already be in the table
                     25:        // count is the number of elements in the array.  May be zero
                     26: int    __remove_old_array(KEYTYP key);
                     27:        // removes an old array from the table.  Returns the count or -1 if not found
                     28: 
                     29: // choose 2 <= DIGIT_SIZE <= 6
                     30: // smaller numbers waste less space and are slower, larger numbers waste more
                     31: // space and are faster
                     32: 
                     33: // control the size of blocks grabbed from the free store (and frequency of
                     34: // allocations) with RECORDS_BLOCK_COUNT and NODES_BLOCK_COUNT
                     35: 
                     36: // a trie based on groups of DIGIT_SIZE bits from the key
                     37: #define DIGIT_SIZE     5
                     38: // each node contains 2 ** DIGIT_SIZE entries
                     39: #define NODE_SIZE      (1 << DIGIT_SIZE)
                     40: #define MASK_BITS      (1 << DIGIT_SIZE) - 1
                     41: // a few low order bits are uninteresting and are rotated around to the top
                     42: #define LOW_BITS       2
                     43: #define LOW_MASK       ((1 << LOW_BITS) - 1)
                     44: // the number of groups in a word
                     45: #define POSITIONS      ((BITS(long) - 1) / DIGIT_SIZE + 1)
                     46: // control the size of blocks grabbed from new
                     47: #define RECORDS_BLOCK_COUNT    150
                     48: #define NODES_BLOCK_COUNT      10
                     49: 
                     50: // avoid name space clashes
                     51: #define pnd __pnd
                     52: #define Node_Pool __Node_Pool
                     53: #define Record_Pool __Record_Pool
                     54: #define pnd_internal_node __pnd_internal_node
                     55: 
                     56: class pnd;
                     57: class pnd_internal_node;
                     58: 
                     59: class RECORD {
                     60: friend pnd;
                     61: friend void    __insert_new_array(KEYTYP addr, int count);
                     62:        inline void*    operator new(size_t);
                     63:        inline void     operator delete(void* p, size_t);
                     64:                inline RECORD(unsigned long k, int cnt);
                     65:                inline ~RECORD();
                     66:        unsigned long   key;    // rotated address of array
                     67:        int     count;  // number of elements of array
                     68: };
                     69: 
                     70: class Record_Pool;
                     71: 
                     72: class Record_shell {
                     73: friend Record_Pool;
                     74:        Record_shell*   next;
                     75:        char    dummy[sizeof(RECORD) - sizeof(Record_shell*)];
                     76: };
                     77: 
                     78: class Record_Pool {
                     79: friend RECORD;
                     80:        static Record_shell*    top;
                     81:                Record_Pool();
                     82:        Record_shell    slot[RECORDS_BLOCK_COUNT];
                     83:        static void*    alloc() {
                     84:                        if (top == 0)
                     85:                                new Record_Pool;
                     86:                        void*   ans = top;
                     87:                        top = top->next;
                     88:                        return ans;
                     89:                }
                     90:        static void     free(Record_shell* p) {
                     91:                        p->next = top;
                     92:                        top = p;
                     93:                }
                     94: };
                     95: 
                     96: inline void*
                     97: RECORD::operator new(size_t)
                     98: {
                     99:        return Record_Pool::alloc();
                    100: }
                    101: inline void
                    102: RECORD::operator delete(void* p, size_t)
                    103: {
                    104:        Record_Pool::free((Record_shell*)p);
                    105: }
                    106: 
                    107: inline
                    108: RECORD::RECORD(unsigned long k, int cnt)
                    109: : key(k), count(cnt)
                    110: {}
                    111: 
                    112: inline RECORD::~RECORD() {}
                    113: 
                    114: class pnd_internal_item {
                    115: friend pnd;
                    116: friend pnd_internal_node;
                    117:        union   {
                    118:                RECORD* ext_leaf;
                    119:                pnd_internal_node*      nodep;
                    120:        };
                    121:        int     this_is_leaf;
                    122:        int     is_node() { return !this_is_leaf && nodep; }
                    123:        int     is_leaf() { return this_is_leaf; }
                    124:        int     is_null() { return !nodep; }
                    125:        pnd_internal_node*      next_node() { return nodep; }
                    126:        RECORD* external_leaf() { return ext_leaf; }
                    127:        void    make_leaf(RECORD* p) { this_is_leaf = 1; ext_leaf = p; }
                    128:        void    make_node(pnd_internal_node* cp) { this_is_leaf = 0; nodep = cp; }
                    129:        void    make_null() {this_is_leaf = 0; nodep = 0; }
                    130: };
                    131: 
                    132: class Node_Pool;
                    133: 
                    134: class pnd_internal_node {
                    135: friend pnd;
                    136: friend void    __insert_new_array(KEYTYP key, int count);
                    137:        inline void*    operator new(size_t i);
                    138:        inline void     operator delete(void* p, size_t i);
                    139:        pnd_internal_node();
                    140:        inline ~pnd_internal_node();
                    141:        pnd_internal_item       item[NODE_SIZE];
                    142:        int     busy_count;
                    143: };
                    144:        
                    145: class Node_shell {
                    146: friend Node_Pool;
                    147:        Node_shell*     next;
                    148:        char    dummy[sizeof(pnd_internal_node) - sizeof(Node_shell*)];
                    149: };
                    150: 
                    151: class Node_Pool {
                    152: friend pnd_internal_node;
                    153:        static Node_shell*      top;
                    154:                Node_Pool();
                    155:        Node_shell      slot[NODES_BLOCK_COUNT];
                    156:        static void*    alloc() {
                    157:                        if (top == 0)
                    158:                                new Node_Pool;
                    159:                        void*   ans = top;
                    160:                        top = top->next;
                    161:                        return ans;
                    162:                }
                    163:        static void     free(void* p) {
                    164:                        ((Node_shell*)p)->next = top;
                    165:                        top = (Node_shell*)p;
                    166:                }
                    167: };
                    168: 
                    169: inline void*
                    170: pnd_internal_node::operator new(size_t)
                    171: {
                    172:        return Node_Pool::alloc();
                    173: }
                    174: inline void
                    175: pnd_internal_node::operator delete(void* p, size_t)
                    176: {
                    177:        Node_Pool::free(p);
                    178: }
                    179: 
                    180: inline pnd_internal_node::~pnd_internal_node() {}
                    181: 
                    182: class pnd  {
                    183: friend void    __insert_new_array(KEYTYP key, int count);
                    184: friend int     __remove_old_array(KEYTYP key);
                    185:        static pnd*     the_table;
                    186:        pnd_internal_item       contents;
                    187:        // int  sze;
                    188:                pnd();
                    189:        static void     initialize();
                    190:        void    insert(KEYTYP, int);
                    191:        int     remove(KEYTYP); // returns count or -1 if not found
                    192: };
                    193: 
                    194: void
                    195: __insert_new_array(KEYTYP key, int count)
                    196: {
                    197:        if (pnd::the_table == 0)
                    198:                pnd::initialize();
                    199:        pnd::the_table->insert(key, count);
                    200: }
                    201: 
                    202: int
                    203: __remove_old_array(KEYTYP key)
                    204: {
                    205:        return pnd::the_table->remove(key);
                    206: }
                    207: 
                    208: pnd_internal_node::pnd_internal_node()
                    209: {
                    210:        register pnd_internal_item*     itemp = &item[0];
                    211:        register int i = NODE_SIZE;
                    212:        while (i--)
                    213:                (itemp++)->make_null();
                    214:        busy_count = 0;
                    215: }
                    216: 
                    217: void
                    218: pnd::insert(KEYTYP addr, int cnt)
                    219: {
                    220:        register unsigned long  mask = MASK_BITS;
                    221:        register unsigned long  key = (unsigned long)addr & LOW_MASK;
                    222:        if (key)
                    223:                key <<= BITS(long) - LOW_BITS;
                    224:        key |= (unsigned long)addr >> LOW_BITS;
                    225:        RECORD* new_rec = new RECORD(key, cnt);
                    226:        register int    unshift = 0;
                    227:        register pnd_internal_item*     itemp = &contents;
                    228:        register pnd_internal_node*     nodep = 0;
                    229:        for (;; mask <<= DIGIT_SIZE, unshift += DIGIT_SIZE) {
                    230:                if (itemp->is_null())
                    231:                        break;
                    232:                if (itemp->is_leaf()) {
                    233:                        if (itemp->external_leaf()->key == key){
                    234:                                itemp->external_leaf()->count = cnt;
                    235:                                delete new_rec;  // didn't need it after all
                    236:                                return; // should rarely happen
                    237:                        }
                    238:                        break;
                    239:                }
                    240:                nodep = itemp->next_node();
                    241:                // assert(nodep);
                    242:                itemp = &nodep->item[(key & mask) >> unshift];
                    243:        }
                    244:        // sze++;
                    245:        if (itemp->is_null()) {
                    246:                itemp->make_leaf(new_rec);
                    247:                if (nodep)
                    248:                        nodep->busy_count++;
                    249:                return;
                    250:        }
                    251:        // assert(itemp->is_leaf());
                    252:        RECORD* temp = itemp->external_leaf();
                    253:        unsigned long   other_key = temp->key;
                    254:        // assert(other_key != key);
                    255:        unsigned long   ind1, ind2;
                    256:        for (;; mask <<= DIGIT_SIZE, unshift += DIGIT_SIZE) {
                    257:                itemp->make_node(nodep = new pnd_internal_node);
                    258:                // assert(pos.curr_depth < POSITIONS);
                    259:                ind1 = (other_key & mask) >> unshift;
                    260:                ind2 = (key & mask) >> unshift;
                    261:                if (ind1 != ind2) break;        // I hope so!
                    262:                nodep->busy_count = 1;
                    263:                itemp = &nodep->item[ind1];
                    264:        }
                    265:        nodep->item[ind1].make_leaf(temp);
                    266:        nodep->item[ind2].make_leaf(new_rec);
                    267:        nodep->busy_count = 2;
                    268:        return;
                    269: }
                    270: 
                    271: int
                    272: pnd::remove(KEYTYP addr)
                    273: {
                    274:        pnd_internal_item*      curr_pos[POSITIONS];
                    275:        int     curr_depth;
                    276:        if (addr == 0) return -1;
                    277:        register unsigned long  mask = MASK_BITS;
                    278:        register unsigned long  key = (unsigned long)addr & LOW_MASK;
                    279:        if (key)
                    280:                key <<= BITS(long) - LOW_BITS;
                    281:        key |= (unsigned long)addr >> LOW_BITS;
                    282:        register int    unshift = 0;
                    283:        register pnd_internal_item*     itemp = &contents;
                    284:        register pnd_internal_node*     nodep = 0;
                    285:        for (curr_depth = -1;; mask <<= DIGIT_SIZE, unshift += DIGIT_SIZE) {
                    286:                // assert(curr_depth < POSITIONS);
                    287:                if (itemp->is_null())
                    288:                        return -1;
                    289:                if (itemp->is_leaf())
                    290:                        if (itemp->external_leaf()->key == key)
                    291:                                break;
                    292:                        else
                    293:                                return -1;
                    294:                nodep = itemp->next_node();
                    295:                // assert(nodep);
                    296:                curr_pos[++curr_depth] = itemp =
                    297:                                &nodep->item[(key & mask) >> unshift];
                    298:        }
                    299:        // assert(itemp->is_leaf());
                    300:        // assert(itemp->external_leaf()->key == key);
                    301:        RECORD* old_p = itemp->external_leaf();
                    302:        // sze--;
                    303:        int     ans = old_p->count;
                    304:        delete old_p;
                    305:        itemp->make_null();
                    306:        if (curr_depth == -1 || // it was a singleton set
                    307:                        --(nodep->busy_count) > 1)      // easy case
                    308:                return ans;
                    309:        // assert(nodep->busy_count == 1);
                    310:        register pnd_internal_item*     itp = &nodep->item[0];
                    311:        while (itp->is_null() || itp == itemp) itp++;
                    312:        if (!itp->is_leaf())    // unfortunate case
                    313:                return ans;
                    314:        RECORD* temp = itp->external_leaf();
                    315:        // assert(temp->key != key);
                    316:        for (;;) {
                    317:                delete nodep;
                    318:                if (curr_depth-- == 0) {
                    319:                        // assert(sze == 1);
                    320:                        contents.make_leaf(temp);
                    321:                        return ans;
                    322:                }
                    323:                nodep = curr_depth == 0 ? contents.next_node() :
                    324:                                curr_pos[curr_depth-1]->next_node();
                    325:                if (nodep->busy_count > 1) {
                    326:                        curr_pos[curr_depth]->make_leaf(temp);
                    327:                        return ans;
                    328:                }
                    329:                // assert(nodep->busy_count == 1);
                    330:        }
                    331: }
                    332: 
                    333: pnd::pnd()
                    334: /* : sze(0) */
                    335: {
                    336:        contents.make_null();
                    337: }
                    338: 
                    339: void
                    340: pnd::initialize()
                    341: {
                    342:        the_table = new pnd;
                    343: }
                    344: 
                    345: Record_Pool::Record_Pool()
                    346: {
                    347:        register int    i = RECORDS_BLOCK_COUNT;
                    348:        register Record_shell*  p = slot;
                    349:        register Record_shell*  q;
                    350:        while (--i) {
                    351:                q = p++;
                    352:                q->next = p;
                    353:        }
                    354:        p->next = top;
                    355:        top = slot;
                    356: }
                    357: 
                    358: Node_Pool::Node_Pool()
                    359: {
                    360:        register int    i = NODES_BLOCK_COUNT;
                    361:        register Node_shell*    p = slot;
                    362:        register Node_shell*    q;
                    363:        while (--i) {
                    364:                q = p++;
                    365:                q->next = p;
                    366:        }
                    367:        p->next = top;
                    368:        top = slot;
                    369: }
                    370: 
                    371: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.