Bloqueando una colecci�n de objetos es bastante f�cil: coges
un spinlock simple, y te aseguras de obtenerlo antes de
buscar, a�adir o borrar un objeto.
El prop�sito de este bloqueo no es proteger los objetos individuales:
quiz�s tengas un bloqueo separado dentro de cada uno de ellos. Es
para proteger la estructura de datos conteniendo el objeto
de las condiciones de carrera. Frecuentemente el
mismo bloqueo es usado tambi�n para proteger los contenidos de
todos los objetos, por simplicidad, pero ellos son inherentemente
ortogonales (y muchas otras grandes palabras dise�adas para
confundir).
Cambiando esto a un bloqueo de lectura-escritura frecuentemente
ayudar� notablemente si las lecturas son m�s frecuentes que las
escrituras. Si no, hay otra aproximaci�n que puedes usar para
reducir el tiempo que es mantenido el bloqueo: las cuentas
de referencia.
En esta aproximaci�n, un objeto tiene un due�o, quien establece
la cuenta de referencia a uno. Cuando obtienes un puntero al
objeto, incrementas la cuenta de referencia (una operaci�n 'obtener').
Cuando abandonas un puntero, decrementas la cuenta de referencia
(una operaci�n 'poner'). Cuando el due�o quiere destruirlo, lo marca
como muerto y hace una operaci�n poner.
Cualquiera que ponga la cuenta de referencia a cero (usualmente
implementado con atomic_dec_and_test())
limpia y libera el objeto.
Esto significa que se garantiza que el objeto no se desvanecer�
debajo de ti, incluso aunque no tengas m�s un bloqueo para la
colecci�n.
Aqu� hay alg�n c�digo esqueleto:
void create_foo(struct foo *x)
{
atomic_set(&x->use, 1);
spin_lock_bh(&list_lock);
... inserta en la lista ...
spin_unlock_bh(&list_lock);
}
struct foo *get_foo(int desc)
{
struct foo *ret;
spin_lock_bh(&list_lock);
... encuentra en la lista ...
if (ret) atomic_inc(&ret->use);
spin_unlock_bh(&list_lock);
return ret;
}
void put_foo(struct foo *x)
{
if (atomic_dec_and_test(&x->use))
kfree(foo);
}
void destroy_foo(struct foo *x)
{
spin_lock_bh(&list_lock);
... borra de la lista ...
spin_unlock_bh(&list_lock);
put_foo(x);
}