コード例 #1
0
ファイル: adtdefs.c プロジェクト: jnorthrup/yap-6.3
OpEntry *
Yap_GetOpProp(Atom a,
              op_type type
                  USES_REGS) { /* look property list of atom a for kind  */
  AtomEntry *ae = RepAtom(a);
  PropEntry *pp;
  OpEntry *oinfo = NULL;

  READ_LOCK(ae->ARWLock);
  pp = RepProp(ae->PropsOfAE);
  while (!EndOfPAEntr(pp)) {
    OpEntry *info = NULL;
    if (pp->KindOfPE != OpProperty) {
      pp = RepProp(pp->NextOfPE);
      continue;
    }
    info = (OpEntry *)pp;
    if (info->OpModule != CurrentModule && info->OpModule != PROLOG_MODULE) {
      pp = RepProp(pp->NextOfPE);
      continue;
    }
    if (type == INFIX_OP) {
      if (!info->Infix) {
        pp = RepProp(pp->NextOfPE);
        continue;
      }
    } else if (type == POSFIX_OP) {
      if (!info->Posfix) {
        pp = RepProp(pp->NextOfPE);
        continue;
      }
    } else {
      if (!info->Prefix) {
        pp = RepProp(pp->NextOfPE);
        continue;
      }
    }
    /* if it is not the latest module */
    if (info->OpModule == PROLOG_MODULE) {
      /* cannot commit now */
      oinfo = info;
      pp = RepProp(pp->NextOfPE);
    } else {
      READ_LOCK(info->OpRWLock);
      READ_UNLOCK(ae->ARWLock);
      return info;
    }
  }
  if (oinfo) {
    READ_LOCK(oinfo->OpRWLock);
    READ_UNLOCK(ae->ARWLock);
    return oinfo;
  }
  READ_UNLOCK(ae->ARWLock);
  return NULL;
}
コード例 #2
0
ファイル: intdict.c プロジェクト: brettmeyers/silk
static void *
int_dict_loookup(
    int                 mode,
    int_dict_t         *dict,
    intkey_t           *key,
    void               *value)
{
    int_dict_node_t target;
    int_dict_node_t *node;

    assert(dict);
    assert(dict->tree);

    if (key != NULL) {
        target.key = *key;
    }

    READ_LOCK(&dict->mutex);
    node = (int_dict_node_t *)rblookup(mode, &target, dict->tree);
    if (node == NULL) {
        RW_MUTEX_UNLOCK(&dict->mutex);
        return NULL;
    }

    if (key != NULL) {
        *key = node->key;
    }
    if (value != NULL) {
        memcpy(value, node->value, dict->value_size);
    }
    RW_MUTEX_UNLOCK(&dict->mutex);

    return node->value;
}
コード例 #3
0
ファイル: intdict.c プロジェクト: brettmeyers/silk
void *
int_dict_next(
    int_dict_iter_t    *iter,
    intkey_t           *key,
    void               *value)
{
    int_dict_node_t *node;

    assert(iter);
    READ_LOCK(&iter->dict->mutex);
    node = (int_dict_node_t *)rbreadlist(iter->list);
    if (node == NULL) {
        RW_MUTEX_UNLOCK(&iter->dict->mutex);
        return NULL;
    }
    if (key != NULL) {
        *key = node->key;
    }

    if (value) {
        memcpy(value, node->value, iter->dict->value_size);
    }
    RW_MUTEX_UNLOCK(&iter->dict->mutex);

    return node->value;
}
コード例 #4
0
ファイル: adtdefs.c プロジェクト: jnorthrup/yap-6.3
static Atom
LookupAtom(const unsigned char *atom) { /* lookup atom in atom table */
  uint64_t hash;
  const unsigned char *p;
  Atom a, na;
  AtomEntry *ae;
  size_t sz = AtomHashTableSize;

  /* compute hash */
  p = atom;

  hash = HashFunction(p);
  hash = hash % sz ;

  /* we'll start by holding a read lock in order to avoid contention */
  READ_LOCK(HashChain[hash].AERWLock);
  a = HashChain[hash].Entry;
  /* search atom in chain */
  na = SearchAtom(atom, a);
  if (na != NIL) {
    READ_UNLOCK(HashChain[hash].AERWLock);
    return (na);
  }
  READ_UNLOCK(HashChain[hash].AERWLock);
  /* we need a write lock */
  WRITE_LOCK(HashChain[hash].AERWLock);
/* concurrent version of Yap, need to take care */
#if defined(YAPOR) || defined(THREADS)
  if (a != HashChain[hash].Entry) {
    a = HashChain[hash].Entry;
    na = SearchAtom(atom, a);
    if (na != NIL) {
      WRITE_UNLOCK(HashChain[hash].AERWLock);
      return (na);
    }
  }
#endif
  /* add new atom to start of chain */
  ae = (AtomEntry *)Yap_AllocAtomSpace((sizeof *ae) +
                                       strlen((const char *)atom) + 1);
  if (ae == NULL) {
    WRITE_UNLOCK(HashChain[hash].AERWLock);
    return NIL;
  }
  NOfAtoms++;
  na = AbsAtom(ae);
  ae->PropsOfAE = NIL;
  if (ae->UStrOfAE != atom)
    strcpy((char *)ae->StrOfAE, (const char *)atom);
  ae->NextOfAE = a;
  HashChain[hash].Entry = na;
  INIT_RWLOCK(ae->ARWLock);
  WRITE_UNLOCK(HashChain[hash].AERWLock);

  if (NOfAtoms > 2 * AtomHashTableSize) {
    Yap_signal(YAP_CDOVF_SIGNAL);
  }
  return na;
}
コード例 #5
0
ファイル: readline.c プロジェクト: vscosta/yap-6.3
static char *atom_enumerate(const char *prefix, int state) {
  CACHE_REGS
  struct scan_atoms *index;
  Atom catom;
  Int i;

  if (!state) {
    index = (struct scan_atoms *)malloc(sizeof(struct scan_atoms));
    i = 0;
    catom = NIL;
  } else {
    CACHE_REGS
    index = LOCAL_search_atoms;
    catom = index->atom;
    i = index->pos;
  }

  while (catom != NIL || i < AtomHashTableSize) {
    //    if ( is_signalled() )		/* Notably allow windows version */
    //      PL_handle_signals();		/* to break out on ^C */
    AtomEntry *ap;

    if (catom == NIL) {
      /* move away from current hash table line */
      READ_LOCK(HashChain[i].AERWLock);
      catom = HashChain[i].Entry;
      READ_UNLOCK(HashChain[i].AERWLock);
      i++;
    } else {
      ap = RepAtom(catom);
      READ_LOCK(ap->ARWLock);
      if (strstr((char *)ap->StrOfAE, prefix) == (char *)ap->StrOfAE) {
        index->pos = i;
        index->atom = ap->NextOfAE;
        LOCAL_search_atoms = index;
        READ_UNLOCK(ap->ARWLock);
        return ap->StrOfAE;
      }
      catom = ap->NextOfAE;
      READ_UNLOCK(ap->ARWLock);
    }
  }
  LOCAL_search_atoms = NULL;
  free(index);
  return NULL;
}
コード例 #6
0
ファイル: xan_uigroupanimation.cpp プロジェクト: olecsys/rux
		Animation& XGroupAnimation::get_Animation( ::rux::uint32 index )
		{
			XAnimation animation;
			READ_LOCK( (*this)()->_cs_animations );
			if( index < (*this)()->_animations.Count() )
				animation = (*this)()->_animations[ index ];
			(*this)()->_cs_animations.ReadUnlock();
			return animation++;
		};
コード例 #7
0
ファイル: adtdefs.c プロジェクト: jnorthrup/yap-6.3
static Prop
GetAProp(Atom a, PropFlags kind) { /* look property list of atom a for kind  */
  AtomEntry *ae = RepAtom(a);
  Prop out;

  READ_LOCK(ae->ARWLock);
  out = GetAPropHavingLock(ae, kind);
  READ_UNLOCK(ae->ARWLock);
  return (out);
}
コード例 #8
0
ファイル: atm.c プロジェクト: MichaelBun/Bank
void balance (char* account_number, char* password,int atm_num)
{
    READ_LOCK(bank_sem_read,bank_sem_write,&bank_readers); //Bank READ
    bool account_found = false;
    bool password_correct = false;
    for(int i=0; i<MAX_ACCOUNT_NUM;i++) //Checking if this acccount exists
    {
        if(account_full[i]==true)
        {
            if((account_ARR[i]->number==atoi(account_number))) //THIS IS THE ACCOUNT
            {
                account_found = true;
                if(!strcmp(account_ARR[i]->password,password)) //password matches
                {
                READ_LOCK(account_ARR[i]->account_sem_read,account_ARR[i]->account_sem_write,&(account_ARR[i]->account_readers));
                password_correct = true;
                sleep(1);
                sem_wait(sem_write_to_log);
                fprintf(log_file,"%d: Account %d balance is %d\n",atm_num+1,account_ARR[i]->number,account_ARR[i]->balance);
                sem_post(sem_write_to_log);
                READ_UNLOCK(account_ARR[i]->account_sem_read,account_ARR[i]->account_sem_write,&(account_ARR[i]->account_readers));
                }
            }
        }
    }

    if(account_found == false)
    {
        sem_wait(sem_write_to_log);
        fprintf(log_file,"Error %d: Your transaction failed - account id %d does not exist\n",atm_num+1,atoi(account_number));
        sem_post(sem_write_to_log);
    }
    else if(password_correct == false)
    {
        sem_wait(sem_write_to_log);
        fprintf(log_file,"Error %d: Your transaction failed - password for account id %d is incorrect\n",atm_num+1,atoi(account_number));
        sem_post(sem_write_to_log);
    }

    READ_UNLOCK(bank_sem_read,bank_sem_write,&bank_readers);

}
コード例 #9
0
ファイル: adtdefs.c プロジェクト: jnorthrup/yap-6.3
Prop Yap_GetPredPropByAtomInThisModule(Atom at, Term cur_mod)
/* get predicate entry for ap/arity; create it if neccessary.              */
{
  Prop p0;
  AtomEntry *ae = RepAtom(at);

  READ_LOCK(ae->ARWLock);
  p0 = GetPredPropByAtomHavingLockInThisModule(ae, cur_mod);
  READ_UNLOCK(ae->ARWLock);
  return (p0);
}
コード例 #10
0
ファイル: atm.c プロジェクト: MichaelBun/Bank
void withdraw(char* account_number, char* password, char* ammount,int atm_num)
{
    READ_LOCK(bank_sem_read,bank_sem_write,&bank_readers); //Bank READ
    int balance_memory; //To remember the balance in the chosen account
    bool account_found = false;
    bool password_correct = false;
    bool enough_money = false;
    for(int i=0; i<MAX_ACCOUNT_NUM;i++) //Checking if this acccount exists
    {
        if(account_full[i]==true)
        {
            if((account_ARR[i]->number==atoi(account_number))) //THIS IS THE ACCOUNT
            {
                account_found = true;
               if(!strcmp(account_ARR[i]->password,password)) //password matches
                {
                    password_correct = true;
                    if(account_ARR[i]->balance >= (balance_memory = atoi(ammount)))
                    {
                        enough_money = true;
                        sem_wait(account_ARR[i]->account_sem_write); //START WRITE
                        sleep(1);
                        account_ARR[i]->balance = account_ARR[i]->balance + atoi(ammount);
                        sem_wait(sem_write_to_log);
                         fprintf(log_file,"%d: Account %d new balance is %d after %d $ was withdrew\n",atm_num+1,account_ARR[i]->number,account_ARR[i]->balance,atoi(ammount));
                         sem_post(sem_write_to_log);
                        sem_post(account_ARR[i]->account_sem_write); //END WRITE
                    }
                }
            }
        }
    }

    if(account_found == false)
    {
        sem_wait(sem_write_to_log);
        fprintf(log_file,"Error %d: Your transaction failed - account id %d does not exist\n",atm_num+1,atoi(account_number));
        sem_post(sem_write_to_log);
    }
    else if(password_correct == false)
    {
        sem_wait(sem_write_to_log);
        fprintf(log_file,"Error %d: Your transaction failed - password for account id %d is incorrect\n",atm_num+1,atoi(account_number));
        sem_post(sem_write_to_log);
    }
    else if(enough_money == false)
    {
        sem_wait(sem_write_to_log);
        fprintf(log_file,"Error %d: Your transaction failed - account id %d balance is lower than %d\n",atm_num+1,atoi(account_number),balance_memory);
        sem_post(sem_write_to_log);
    }

    READ_UNLOCK(bank_sem_read,bank_sem_write,&bank_readers);
}
コード例 #11
0
/* expects */
static void *exp_seq_start(struct seq_file *s, loff_t *pos)
{
	struct list_head *e = &ip_conntrack_expect_list;
	loff_t i;

	/* strange seq_file api calls stop even if we fail,
	 * thus we need to grab lock since stop unlocks */
	READ_LOCK(&ip_conntrack_lock);
	READ_LOCK(&ip_conntrack_expect_tuple_lock);

	if (list_empty(e))
		return NULL;

	for (i = 0; i <= *pos; i++) {
		e = e->next;
		if (e == &ip_conntrack_expect_list)
			return NULL;
	}
	return e;
}
コード例 #12
0
/* Print out the private part of the conntrack. */
static int tcp_print_conntrack(struct seq_file *s,
			       const struct ip_conntrack *conntrack)
{
	enum tcp_conntrack state;

	READ_LOCK(&tcp_lock);
	state = conntrack->proto.tcp.state;
	READ_UNLOCK(&tcp_lock);

	return seq_printf(s, "%s ", tcp_conntrack_names[state]);
}
コード例 #13
0
ファイル: adtdefs.c プロジェクト: tacgomes/yap6.3
Prop
Yap_GetPredPropByFuncInThisModule(Functor f, Term cur_mod)
     /* get predicate entry for ap/arity;               */
{
  Prop p0;

  READ_LOCK(f->FRWLock);
  p0 = GetPredPropByFuncHavingLock(f, cur_mod);
  READ_UNLOCK(f->FRWLock);
  return (p0);
}
コード例 #14
0
/* Print out the private part of the conntrack. */
static unsigned int tcp_print_conntrack(char *buffer,
					const struct ip_conntrack *conntrack)
{
	enum tcp_conntrack state;

	READ_LOCK(&tcp_lock);
	state = conntrack->proto.tcp.state;
	READ_UNLOCK(&tcp_lock);

	return sprintf(buffer, "%s ", tcp_conntrack_names[state]);
}
コード例 #15
0
ファイル: adtdefs.c プロジェクト: jnorthrup/yap-6.3
/* get expression entry for at/arity;               */
Prop Yap_GetExpProp(Atom at, unsigned int arity) {
  Prop p0;
  AtomEntry *ae = RepAtom(at);
  ExpEntry *p;

  READ_LOCK(ae->ARWLock);
  p = RepExpProp(p0 = ae->PropsOfAE);
  while (p0 && (p->KindOfPE != ExpProperty || p->ArityOfEE != arity))
    p = RepExpProp(p0 = p->NextOfPE);
  READ_UNLOCK(ae->ARWLock);
  return (p0);
}
コード例 #16
0
static int ct_seq_show(struct seq_file *s, void *v)
{
	struct list_head *list = v;
	int ret = 0;

	/* FIXME: Simply truncates if hash chain too long. */
	READ_LOCK(&ip_conntrack_lock);
	if (LIST_FIND(list, ct_seq_real_show,
		      struct ip_conntrack_tuple_hash *, s))
		ret = -ENOSPC;
	READ_UNLOCK(&ip_conntrack_lock);
	return ret;
}
コード例 #17
0
PUBLIC int
avl_tree_traverse (avl_tree_t *tree,
        traverse_function_pointer tfn,
        void *p0, void *p1, void *p2, void *p3)
{
    int rv;

    READ_LOCK(tree);
    rv = thread_unsafe_morris_traverse(tree, tree->root_node,
                tfn, p0, p1, p2, p3);
    READ_UNLOCK(tree);
    return rv;
}
コード例 #18
0
static int
match(const struct sk_buff *skb,
      const struct net_device *in,
      const struct net_device *out,
      const void *matchinfo,
      int offset,
      int *hotdrop)
{
	const struct ipt_helper_info *info = matchinfo;
	struct ip_conntrack_expect *exp;
	struct ip_conntrack *ct;
	enum ip_conntrack_info ctinfo;
	int ret = info->invert;
	
	ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
	if (!ct) {
		DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
		return ret;
	}

	if (!ct->master) {
		DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
		return ret;
	}

	exp = ct->master;
	READ_LOCK(&ip_conntrack_lock);
	if (!exp->expectant) {
		DEBUGP("ipt_helper: expectation %p without expectant !?!\n", 
			exp);
		goto out_unlock;
	}

	if (!exp->expectant->helper) {
		DEBUGP("ipt_helper: master ct %p has no helper\n", 
			exp->expectant);
		goto out_unlock;
	}

	DEBUGP("master's name = %s , info->name = %s\n", 
		exp->expectant->helper->name, info->name);

	if (info->name[0] == '\0')
		ret ^= 1;
	else
		ret ^= !strncmp(exp->expectant->helper->name, info->name, 
		                strlen(exp->expectant->helper->name));
out_unlock:
	READ_UNLOCK(&ip_conntrack_lock);
	return ret;
}
コード例 #19
0
ファイル: xan_uigroupanimation.cpp プロジェクト: olecsys/rux
		rux::uint64 GroupAnimation::get_Duration( void )
		{
			if( _duration == 0 )
			{
				READ_LOCK( _cs_animations );
				for( size_t index0 = 0 ; index0 < _animations.Count() ; index0++ )
				{
					if( _animations[ index0 ].get_Duration() > _duration )
						_duration = _animations[ index0 ].get_Duration();
				}
				_cs_animations.ReadUnlock();
			}
			return _duration;
		};
コード例 #20
0
/* Print out the private part of the conntrack. */
static int sctp_print_conntrack(struct seq_file *s,
				const struct ip_conntrack *conntrack)
{
	enum sctp_conntrack state;

	DEBUGP(__FUNCTION__);
	DEBUGP("\n");

	READ_LOCK(&sctp_lock);
	state = conntrack->proto.sctp.state;
	READ_UNLOCK(&sctp_lock);

	return seq_printf(s, "%s ", sctp_conntrack_names[state]);
}
コード例 #21
0
ファイル: errors.c プロジェクト: jfmc/yap-6.3
static int
hidden (Atom at)
{
  AtomEntry *chain;
  
  READ_LOCK(INVISIBLECHAIN.AERWLock);
  chain = RepAtom(INVISIBLECHAIN.Entry);
  while (!EndOfPAEntr (chain) && AbsAtom (chain) != at)
    chain = RepAtom(chain->NextOfAE);
  READ_UNLOCK(INVISIBLECHAIN.AERWLock);
  if (EndOfPAEntr (chain))
    return (FALSE);
  return (TRUE);
}
コード例 #22
0
ファイル: adtdefs.c プロジェクト: jnorthrup/yap-6.3
inline static Atom SearchInInvisible(const unsigned char *atom) {
  AtomEntry *chain;

  READ_LOCK(INVISIBLECHAIN.AERWLock);
  chain = RepAtom(INVISIBLECHAIN.Entry);
  while (!EndOfPAEntr(chain) && strcmp((char *)chain->StrOfAE, (char *)atom)) {
    chain = RepAtom(chain->NextOfAE);
  }
  READ_UNLOCK(INVISIBLECHAIN.AERWLock);
  if (EndOfPAEntr(chain))
    return (NIL);
  else
    return (AbsAtom(chain));
}
コード例 #23
0
ファイル: adtdefs.c プロジェクト: jnorthrup/yap-6.3
int Yap_HasOp(Atom a) { /* look property list of atom a for kind  */
  AtomEntry *ae = RepAtom(a);
  PropEntry *pp;

  READ_LOCK(ae->ARWLock);
  pp = RepProp(ae->PropsOfAE);
  while (!EndOfPAEntr(pp) && (pp->KindOfPE != OpProperty))
    pp = RepProp(pp->NextOfPE);
  READ_UNLOCK(ae->ARWLock);
  if (EndOfPAEntr(pp)) {
    return FALSE;
  } else {
    return TRUE;
  }
}
コード例 #24
0
/** get  entry for ap/arity; assumes one is there.              */
static ModEntry *FetchModuleEntry(Atom at) {
  Prop p0;
  AtomEntry *ae = RepAtom(at);

  READ_LOCK(ae->ARWLock);
  p0 = ae->PropsOfAE;
  while (p0) {
    ModEntry *me = RepModProp(p0);
    if (me->KindOfPE == ModProperty) {
      READ_UNLOCK(ae->ARWLock);
      return me;
    }
    p0 = me->NextOfPE;
  }
  READ_UNLOCK(ae->ARWLock);
  return NULL;
}
コード例 #25
0
ファイル: adtdefs.c プロジェクト: tacgomes/yap6.3
Prop
Yap_GetPredPropHavingLock(Atom ap, unsigned int arity, Term mod)
     /* get predicate entry for ap/arity;               */
{
  Prop p0;
  AtomEntry *ae = RepAtom(ap);
  Functor f;

  if (arity == 0) {
    GetPredPropByAtomHavingLock(ae, mod);
  }
  f = InlinedUnlockedMkFunctor(ae, arity);
  READ_LOCK(f->FRWLock);
  p0 = GetPredPropByFuncHavingLock(f, mod);
  READ_UNLOCK(f->FRWLock);
  return (p0);
}
コード例 #26
0
ファイル: bb.c プロジェクト: davidvaz/yap-udi
static BBProp 
GetBBProp(AtomEntry *ae, Term mod)		/* get BBentry for at; */
{
  Prop          p0;
  BBProp        p;

  READ_LOCK(ae->ARWLock);
  p = RepBBProp(p0 = ae->PropsOfAE);
  while (p0 != NIL && (!IsBBProperty(p->KindOfPE) ||
		(p->ModuleOfBB != mod))) {
    p = RepBBProp(p0 = p->NextOfPE);
  }
  READ_UNLOCK(ae->ARWLock);
  if (p0 == NIL) {
    return(NULL);
  }
  return (p);
}
コード例 #27
0
/**
 * get predicate entry for ap/arity; create it if neccessary
 *
 * @param[in] at
 *
 * @return module descriptorxs
 */
static ModEntry *GetModuleEntry(Atom at USES_REGS) {
  Prop p0;
  AtomEntry *ae = RepAtom(at);

  READ_LOCK(ae->ARWLock);
  p0 = ae->PropsOfAE;
  while (p0) {
    ModEntry *me = RepModProp(p0);
    if (me->KindOfPE == ModProperty) {
      READ_UNLOCK(ae->ARWLock);
      return me;
    }
    p0 = me->NextOfPE;
  }
  READ_UNLOCK(ae->ARWLock);

  return initMod(
      (CurrentModule == PROLOG_MODULE ? NULL : AtomOfTerm(CurrentModule)), at);
}
コード例 #28
0
ファイル: xan_uigroupanimation.cpp プロジェクト: olecsys/rux
		void GroupAnimation::Start( ::rux::byte anew )
		{
			WRITE_LOCK( _cs_animation_schedule_index );
			if( _animation_schedule_index == SIZE_MAX )
			{
				_stop_is_executed = 0;
				_start_time = ::rux::XTime::GetTickCount();	
				READ_LOCK( _cs_animations );
				for( size_t index0 = 0 ; index0 < _animations.Count() ; index0++ )
					_animations[ index0 ].Start();
				_cs_animations.ReadUnlock();
				_animation_schedule_index = ::rux::gui::application::add_schedule( XGroupAnimation::private_Animation , this , 20000ULL );
			}
			else if( anew )
			{
				_stop_is_executed = 0;
				_start_time = ::rux::XTime::GetTickCount();	
			}
			_cs_animation_schedule_index.WriteUnlock();
		};
コード例 #29
0
PUBLIC int 
avl_tree_search (avl_tree_t *tree, 
        void *data_to_be_searched,
        void **data_found)
{
    int rv;
    avl_node_t *parent, *unbalanced, *node;
    int is_left;

    READ_LOCK(tree);
    node = avl_lookup_engine(tree, data_to_be_searched, 
                &parent, &unbalanced, &is_left);
    if (node) {
        *data_found = node->user_data;
        rv = 0;
    } else {
        *data_found = NULL;
        rv = ENODATA;
    }
    READ_UNLOCK(tree);
    return rv;
}
コード例 #30
0
ファイル: intdict.c プロジェクト: brettmeyers/silk
int_dict_iter_t *
int_dict_open(
    int_dict_t         *dict)
{
    int_dict_iter_t *iter;

    assert(dict);

    iter = (int_dict_iter_t*)malloc(sizeof(int_dict_iter_t));
    if (iter == NULL) {
        return NULL;
    }
    iter->dict = dict;
    READ_LOCK(&dict->mutex);
    iter->list = rbopenlist(dict->tree);
    RW_MUTEX_UNLOCK(&dict->mutex);
    if (iter->list == NULL) {
        free(iter);
        return NULL;
    }
    return iter;
}