c++ - Manejar conexión/desconexión de muchas señales/ranuras con boost:: signals2
boost-signals2 (2)
No lo he probado solo, pero de acuerdo con la documentación de impulso
¿Cuándo pueden ocurrir las desconexiones? (Intermedio)
Las desconexiones de señal / ranura ocurren cuando ocurre cualquiera de estas condiciones:
- La conexión se desconecta explícitamente mediante el método de
disconnect
la conexión directamente, o indirectamente a través del método dedisconnect
la señal, o elscoped_connection
descoped_connection
.- Un objeto rastreado por la ranura se destruye.
- La señal se destruye.
A menos que use un scoped_connection
la conexión entre una señal y una ranura seguirá siendo válida hasta que se destruya cualquiera de ellas. Por lo que entiendo, no es necesario almacenar objetos de conexión en un vector. Simplemente conecte su señal a su ranura como lo está haciendo ahora.
Cuando su objeto observado se sale del alcance, eliminará la conexión por sí mismo.
Este es un diseño mucho más simple.
Empecé a usar boost :: signals2 en lugar de mi antiguo código de señales. Aunque estoy teniendo un problema con la administración de múltiples conexiones. Aquí está mi problema:
Tengo muchas instancias de la clase Persona:
class Person {
public:
void SetName (string new_name)
{
name = new_name;
NameChange (name);
}
string name;
boost::signals2::signal<Person*> NameChange;
};
También tengo un navegador de personas, que debe monitorear un subconjunto de todas las personas disponibles para los cambios. Como las personas pueden ir y venir de ese subconjunto, debo tener una forma de manejar los objetos de conexión, y he creado una clase (ConnectionList) para manejar eso:
class ConnectionList
{
public:
virtual ~ConnectionList () // drops all connections in "list"
void add (boost::signals2::connection& conn); // adds "conn" to "list"
private:
std::vector<boost::signals2::connection> list;
};
class PeopleBrowser
{
public:
void AddPerson (Person& p)
{
name_change_connections.add (p.NameChange.connect (...));
}
private:
ConnectionList name_change_connections;
};
Todo está bien, las conexiones se eliminan cuando se borra PeopleBrowser y hay una buena manera de agregar nuevas conexiones.
Sin embargo, necesitamos agregar otro método, RemovePerson, y ese método debe eliminar las conexiones a la señal NameChange de esa persona-instancia.
Aquí es donde estoy atascado. Creo que podría hacer de ConnectionList una plantilla y usar una lista que contenga una estructura con una referencia a la señal y a la conexión, y luego agregar un método que elimine todas las conexiones a esa señal.
Pero parece que este es un caso tan común (al menos en mi mundo, tengo 20 clases en esta aplicación única que necesita esta funcionalidad), ¿así que creo que debe haber una forma mejor de manejar esto?
Por lo menos, ¿hay alguna forma de obtener una referencia a la señal conectada desde un objeto de conexión?
Quizás libsigc ++ maneje esto mejor / diferente?
Qué pasa:
class PeopleBrowser
{
public:
void AddPerson (Person& p)
{
name_change_connections[&p] = p.NameChange.connect(...);
}
void RemovePerson(Person& p)
{
name_change_connections.erase(&p);
}
private:
std::map<Person*, boost::signals2::scoped_connection> name_change_connections;
};
También es posible que desee echar un vistazo a la gestión de conexión automática .