} 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++ ){
} 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; }