} t_tmbk;

/*
 * We use 8 Bits of the klass object id as index to a 256 entry cache.
 * This avoids full lookups in most cases.
 */
#define CACHE_LOOKUP(this, klass) ( &this->cache_row[(klass >> 8) & 0xff] )


static t_pg_coder *
pg_tmbk_lookup_klass(t_tmbk *this, VALUE klass, VALUE param_value)
{
	t_pg_coder *p_coder;
	struct pg_tmbk_coder_cache_entry *p_ce;

	p_ce = CACHE_LOOKUP(this, klass);

	/* Is the cache entry for the expected klass? */
	if( p_ce->klass == klass ) {
		p_coder = p_ce->p_coder;
	} else {
		/* No, then do a full lookup based on the ancestors. */
		VALUE obj = rb_hash_lookup( this->klass_to_coder, klass );

		if( NIL_P(obj) ){
			int i;
			VALUE ancestors = rb_funcall( klass, s_id_ancestors, 0 );

			Check_Type( ancestors, T_ARRAY );
			/* Don't look at the first element, it's expected to equal klass. */
			for( i=1; i<RARRAY_LEN(ancestors); i++ ){
示例#2
0
	} format[2];
} t_tmbo;

/*
 * We use the OID's minor 8 Bits as index to a 256 entry cache. This avoids full ruby hash lookups
 * for each value in most cases.
 */
#define CACHE_LOOKUP(this, form, oid) ( &this->format[(form)].cache_row[(oid) & 0xff] )

static t_pg_coder *
pg_tmbo_lookup_oid(t_tmbo *this, int format, Oid oid)
{
	t_pg_coder *conv;
	struct pg_tmbo_oid_cache_entry *p_ce;

	p_ce = CACHE_LOOKUP(this, format, oid);

	/* Has the entry the expected OID and is it a non empty entry? */
	if( p_ce->oid == oid && (oid || p_ce->p_coder) ) {
		conv = p_ce->p_coder;
	} else {
		VALUE obj = rb_hash_lookup( this->format[format].oid_to_coder, UINT2NUM( oid ));
		/* obj must be nil or some kind of PG::Coder, this is checked at insertion */
		conv = NIL_P(obj) ? NULL : DATA_PTR(obj);
		/* Write the retrieved coder to the cache */
		p_ce->oid = oid;
		p_ce->p_coder = conv;
	}
	return conv;
}