FastCollectionsByLeo/Src/ColHash/HashBases/README.md
2026-09-03 11:03:46 -05:00

4.3 KiB

Uso de bajo nivel de CFastHashTableBase

Esta guía es solo para quien quiere exprimir el rendimiento al máximo y está dispuesto a acoplarse al estado interno del algoritmo. Si solo usas la API normal (Add, TryGet, Contains, Remove(key), etc.) no necesitas leer esto — este documento describe los miembros públicos "residuales" (m_i, m_bit_pos, m_last_pos_tbl) que el motor deja expuestos para evitar un segundo recorrido de la tabla (el clásico patrón find + luego add/replace hecho en una sola pasada).

Estos tres campos no son un resultado estable: su valor solo tiene sentido inmediatamente después de la llamada que los dejó ahí, y cualquier otra llamada al mismo hashmap los vuelve a pisar (incluida una llamada anidada dentro de la misma expresión). No los guardes para usarlos más tarde.

Los tres campos

Campo Qué es
m_i Índice de grupo (grupo de 8 slots) donde terminó la búsqueda.
m_bit_pos Posición dentro del grupo, (multiplo de 8) - 1, en Remove* puede ser multiplo de ((8)-1)-7
m_last_pos_tbl Índice absoluto y ya resuelto en m_table[]. Es el único que puedes indexar directamente sin más cálculo.

m_last_pos_tbl existe justamente para que no tengas que calcular nada: siempre que un método lo garantice actualizado (ver tabla), puedes hacer m_table[m_last_pos_tbl] directo. m_i y m_bit_pos son el detalle interno que lo construye, expuestos solo para casos muy puntuales de bajo nivel (por ejemplo, Remove los reutiliza sin tener que rebuscar la key).

Qué deja cada método, exactamente

Método Retorno m_i m_bit_pos m_last_pos_tbl
ReserveSlot(key) false (ya existía) grupo del slot existente (sin uso) posición exacta de la key existente
ReserveSlot(key) true (no existía, se reservó) grupo del slot nuevo (sin uso) posición del slot recién reservado (sin key todavía escrita — eso te toca a ti)
ContainsKey(key) / ContainsKeyByHash(hash) true grupo del match bit-pos (múltiplo de 8, +7 → 7,15,23…63) posicion inicial del grupo en bit posición exacta del match
ContainsKey(key) / ContainsKeyByHash(hash) false último grupo probado ultima posicion probada en grupo sin significado
Remove(key) true igual que el ContainsKey interno que usa Mismo valor que ContainsKey - 7 posición exacta del match (true)
Remove(key) false último grupo probado ultima posicion probada en grupo sin significado
RemoveLastFindCall() usa el m_i/m_bit_pos que haya dejado la llamada previa a ContainsKey/ContainsKeyByHash Valor reducido en 7

Patrón recomendado (find-or-insert en una sola pasada)

if(!hashmap.ReserveSlot(key))
 {
  // Ya existía → reemplazar/leer directo, sin recalcular nada
  hashmap.m_table[hashmap.m_last_pos_tbl].value = nuevo_valor;
 }
else
 {
  // No existía → el slot ya está reservado, solo falta llenar key/value
  hashmap.m_table[hashmap.m_last_pos_tbl].key   = key;
  hashmap.m_table[hashmap.m_last_pos_tbl].value = nuevo_valor;
 }

Este es el patrón que usan CDomNodeBase::Set() y operator[] en BasesParserSLan para evitar un Find + Add por separado.

Advertencia sobre re-entrancia

Estos campos son miembros de instancia, no valores locales por-llamada. Si entre que guardas la intención de usarlos y realmente los usas se cuela cualquier otra llamada al mismo hashmap (otro ReserveSlot, ContainsKey, Remove, o un Reserve/Rehash disparado internamente por estar cerca del límite de resize), el valor queda pisado. Usa siempre m_last_pos_tbl inmediatamente después de la llamada que lo dejó, nunca lo arrastres a través de otra operación sobre el mismo objeto.