pike.git / src / mapping.c

version» Context lines:

pike.git/src/mapping.c:1:   /*   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: mapping.c,v 1.201 2008/05/11 14:55:53 mast Exp $ + || $Id: mapping.c,v 1.202 2008/06/24 18:45:56 grubba Exp $   */      #include "global.h"   #include "main.h"   #include "object.h"   #include "mapping.h"   #include "svalue.h"   #include "array.h"   #include "pike_macros.h"   #include "pike_error.h"
pike.git/src/mapping.c:198:    mark_free_svalue (&md->free_list[e-1].val);   #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */    md->ind_types = 0;    md->val_types = 0;    md->flags = flags;    md->size = 0;    md->refs=0;    md->valrefs=0;    md->hardlinks=0;    md->num_keypairs=size; +  md->generation_cnt = 0;    }else{    switch (flags & MAPPING_WEAK) {    case 0: md = &empty_data; break;    case MAPPING_WEAK_INDICES: md = &weak_ind_empty_data; break;    case MAPPING_WEAK_VALUES: md = &weak_val_empty_data; break;    default: md = &weak_both_empty_data; break;    }    }    add_ref(md);    m->data=md;
pike.git/src/mapping.c:410: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if(md->refs <=0)    Pike_fatal("Zero refs in mapping->data\n");       if(d_flag>1) check_mapping(m);   #endif       init_mapping(m, new_size, md->flags);    debug_malloc_touch(m);    new_md=m->data; +  new_md->generation_cnt = md->generation_cnt;       /* This operation is now 100% atomic - no locking required */    if(md->refs>1)    {    /* good */    for(e=0;e<md->hashsize;e++)    mapping_rehash_backwards_good(new_md, md->hash[e]);       unlink_mapping_data(md);    }else{
pike.git/src/mapping.c:494:    RELOC(keypairs[e].next);    add_ref_svalue(& keypairs[e].ind);    add_ref_svalue(& keypairs[e].val);    }   #endif /* PIKE_MAPPING_KEYPAIR_LOOP */       nmd->refs=0;    add_ref(nmd); /* For DMALLOC... */    nmd->valrefs=0;    nmd->hardlinks=0; +  nmd->generation_cnt = md->generation_cnt;    -  +  /* FIXME: What about nmd->flags? */ +     if(md->hardlinks)    {   #ifdef PIKE_DEBUG    if(md->refs <= 0 || md->valrefs<=0)    Pike_fatal("Hardlink without refs/valrefs!\n");   #endif    md->hardlinks--;    md->valrefs--;    }    sub_ref(md);
pike.git/src/mapping.c:741:    free_mapping_data(md);    if(!overwrite) return;    PREPARE_FOR_DATA_CHANGE2();    PROPAGATE(); /* propagate after preparing */    md->val_types |= 1 << val->type;    if (overwrite == 2 && key->type == T_OBJECT)    /* Should replace the index too. It's only for objects that it's    * possible to tell the difference. */    assign_svalue (&k->ind, key);    assign_svalue(& k->val, val); +  md->flags |= MAPPING_DIRTY;   #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif    return;       mi_insert:   #ifdef PIKE_DEBUG    if(m->data != md)    Pike_fatal("Wrong dataset in mapping_insert!\n");    if(d_flag>1) check_mapping(m);
pike.git/src/mapping.c:789:    md->val_types |= 1 << val->type;    assign_svalue_no_free(& k->ind, key);    assign_svalue_no_free(& k->val, val);    k->hval = h2;    md->size++;   #ifdef MAPPING_SIZE_DEBUG    if(m->data ==md)    m->debug_size++;   #endif    +  md->flags |= MAPPING_DIRTY; +    #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif   }      PMOD_EXPORT void mapping_insert(struct mapping *m,    const struct svalue *key,    const struct svalue *val)   {    low_mapping_insert(m,key,val,1);
pike.git/src/mapping.c:908:    k->next=md->hash[h];    md->hash[h]=k;    assign_svalue_no_free(& k->ind, key);    k->val.type=T_INT;    k->val.subtype=NUMBER_NUMBER;    k->val.u.integer=0;    k->hval = h2;    md->ind_types |= 1 << key->type;    md->val_types |= BIT_INT;    md->size++; +  md->flags |= MAPPING_DIRTY;   #ifdef MAPPING_SIZE_DEBUG    if(m->data ==md)    m->debug_size++;   #endif      #ifdef PIKE_DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif       return & ( k->val.u );
pike.git/src/mapping.c:992:       md->size--;   #ifdef MAPPING_SIZE_DEBUG    if(m->data ==md)    m->debug_size--;   #endif       if(md->size < (md->hashsize + 1) * MIN_LINK_LENGTH)    {    debug_malloc_touch(m); -  rehash(m, MAP_SLOTS(m->data->size)); +  rehash(m, MAP_SLOTS(m->data->size + !!md->generation_cnt));    }    -  +  /* Note: md may be invalid here dure to the rehash above. */ +  m->data->flags |= MAPPING_DIRTY; +    #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif    return;   }      PMOD_EXPORT void check_mapping_for_destruct(struct mapping *m)   {    INT32 e;    struct keypair *k, **prev;
pike.git/src/mapping.c:1044:    debug_malloc_touch(m);    debug_malloc_touch(md);    PREPARE_FOR_INDEX_CHANGE2();    *prev=k->next;    free_svalue(& k->ind);    free_svalue(& k->val);    FREE_KEYPAIR(md, k);    mark_free_svalue (&md->free_list->ind);    mark_free_svalue (&md->free_list->val);    md->size--; +  +  md->flags |= MAPPING_DIRTY; +    #ifdef MAPPING_SIZE_DEBUG    if(m->data ==md)    {    m->debug_size++;    debug_malloc_touch(m);    }   #endif    debug_malloc_touch(md);    }else{    val_types |= 1 << k->val.type;    ind_types |= 1 << k->ind.type;    prev=&k->next;    }    }    }       md->val_types = val_types;    md->ind_types = ind_types;    -  if(MAP_SLOTS(md->size) < md->hashsize * MIN_LINK_LENGTH) +  if(MAP_SLOTS(md->size + !!md->generation_cnt) < +  md->hashsize * MIN_LINK_LENGTH)    {    debug_malloc_touch(m); -  rehash(m, MAP_SLOTS(md->size)); +  rehash(m, MAP_SLOTS(md->size + !!md->generation_cnt));    }      #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif    }   }      PMOD_EXPORT struct svalue *low_mapping_lookup(struct mapping *m,    const struct svalue *key)
pike.git/src/mapping.c:1333:    if(md->size)    {    add_ref(md);    NEW_MAPPING_LOOP(md)    {    if(is_eq(& k->val, from))    {    PREPARE_FOR_DATA_CHANGE();    assign_svalue(& k->val, to);    md->val_types|=1<<to->type; +  md->flags |= MAPPING_DIRTY;    }    }    free_mapping_data(md);    }      #ifdef PIKE_DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif   }   
pike.git/src/mapping.c:1485:    for (k2 = a_md->hash[h]; k2; k2 = k2->next) {    if ((k2->hval == k->hval) && is_eq(&k2->ind, &k->ind)) {    break;    }    }    if (!k2) {    map_delete(res, &k->ind);    }    }    UNSET_ONERROR(err); +  if (a_md->generation_cnt > b_md->generation_cnt) +  res->generation_cnt = a_md->generation_cnt; +  else +  res->generation_cnt = b_md->generation_cnt;    return res;   }      static struct mapping *or_mappings(struct mapping *a, struct mapping *b)   {    struct mapping *res;    struct keypair *k;    struct mapping_data *a_md = a->data;    struct mapping_data *b_md = b->data;    INT32 e;
pike.git/src/mapping.c:1520:    for (k2 = b_md->hash[h]; k2; k2 = k2->next) {    if ((k2->hval == k->hval) && is_eq(&k2->ind, &k->ind)) {    break;    }    }    if (!k2) {    mapping_insert(res, &k->ind, &k->val);    }    }    UNSET_ONERROR(err); +  if (a_md->generation_cnt > b_md->generation_cnt) +  res->generation_cnt = a_md->generation_cnt; +  else +  res->generation_cnt = b_md->generation_cnt;    return res;   }      static struct mapping *xor_mappings(struct mapping *a, struct mapping *b)   {    struct mapping *res;    struct keypair *k;    struct mapping_data *a_md = a->data;    struct mapping_data *b_md = b->data;    INT32 e;
pike.git/src/mapping.c:1564:    break;    }    }    if (!k2) {    mapping_insert(res, &k->ind, &k->val);    } else {    map_delete(res, &k2->ind);    }    }    UNSET_ONERROR(err); +  if (a_md->generation_cnt > b_md->generation_cnt) +  res->generation_cnt = a_md->generation_cnt; +  else +  res->generation_cnt = b_md->generation_cnt;    return res;   }      PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op)   {    ONERROR r1,r2,r3,r4;    struct array *ai, *av;    struct array *bi, *bv;    struct array *ci, *cv;    INT32 *zipper;
pike.git/src/mapping.c:1640:       UNSET_ONERROR(r2); free_array(bv);    UNSET_ONERROR(r1); free_array(av);       free((char *)zipper);       m=mkmapping(ci, cv);    free_array(ci);    free_array(cv);    +  if (a->data->generation_cnt > b->data->generation_cnt) +  m->generation_cnt = a->data->generation_cnt; +  else +  m->generation_cnt = b->data->generation_cnt;    return m;   }      /* FIXME: What are the semantics for this function?    * FIXME: It ought to be optimized just like the unordered variant.    * /grubba 2003-11-12    */   PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a,    struct array *b, INT32 op)   {
pike.git/src/mapping.c:1693:       UNSET_ONERROR(r2); free_array(av);    UNSET_ONERROR(r1); free_array(ai);       free((char *)zipper);       m=mkmapping(ci, cv);    free_array(ci);    free_array(cv);    +  if (a->data->generation_cnt > b->data->generation_cnt) +  m->generation_cnt = a->data->generation_cnt; +  else +  m->generation_cnt = b->data->generation_cnt;    return m;   }      PMOD_EXPORT struct mapping *merge_mapping_array_unordered(struct mapping *a,    struct array *b, INT32 op)   {    ONERROR r1;    struct array *b_temp;    INT32 *zipper;    struct mapping *m;
pike.git/src/mapping.c:1724:    m=merge_mapping_array_ordered(a,b,op);       return m;   }      PMOD_EXPORT struct mapping *add_mappings(struct svalue *argp, INT32 args)   {    INT32 e,d;    struct mapping *ret=0;    struct keypair *k; +  int generation = 0;       for(e=d=0;d<args;d++)    { -  +  struct mapping *m = argp[d].u.mapping;   #ifdef PIKE_DEBUG -  if(d_flag>1) check_mapping(argp[d].u.mapping); +  if(d_flag>1) check_mapping(m);   #endif -  e+=argp[d].u.mapping->data->size; +  e += m->data->size;    }       if(!e) return allocate_mapping(0);       d=0;       for(;d<args;d++)    {    struct mapping *m=argp[d].u.mapping;    struct mapping_data *md=m->data;
pike.git/src/mapping.c:1768:    ret=allocate_mapping(MAP_SLOTS(e));    break;       }       for(;d<args;d++)    {    struct mapping *m=argp[d].u.mapping;    struct mapping_data *md=m->data;    +  if (md->generation_cnt > generation) +  generation = md->generation_cnt; +     add_ref(md);    NEW_MAPPING_LOOP(md)    low_mapping_insert(ret, &k->ind, &k->val, 2);    free_mapping_data(md);    }   #ifdef PIKE_DEBUG    if(!ret)    Pike_fatal("add_mappings is confused!\n");   #endif -  +  ret->md->generation_cnt = generation;    return ret;   }      PMOD_EXPORT int mapping_equal_p(struct mapping *a, struct mapping *b, struct processing *p)   {    struct processing curr;    struct keypair *k;    struct mapping_data *md;    INT32 e,eq=1;   
pike.git/src/mapping.c:2189:       md->valrefs--;    free_mapping_data(md);    }       to->type=T_INT;    to->subtype=NUMBER_UNDEFINED;    to->u.integer=0;   }    + PMOD_EXPORT INT32 mapping_generation(struct mapping *m) + { +  if (m->data->flags & MAPPING_DIRTY) { +  m->data->generation_cnt++; +  m->data->flags &= ~MAPPING_DIRTY; +  } +  return m->data->generation_cnt; + }      #ifdef PIKE_DEBUG      void check_mapping(const struct mapping *m)   {    int e,num;    struct keypair *k;    const struct mapping_data *md;       static int in_check_mapping;