Pregunta

¿Alguien sabe dónde puedo encontrar una implementación que contenga un std :: map y lo haga seguro para los hilos? Cuando digo hilo seguro, quiero decir que ofrece solo acceso en serie al mapa, un hilo a la vez. De manera óptima, este mapa debería usar solo las construcciones estándar de biblioteca y / o boost.

¿Fue útil?

Solución

No cumple con los criterios que ha especificado, pero puede echar un vistazo a los contenedores TBB . Existe el llamado concurrent_hash_map que permite que múltiples subprocesos accedan simultáneamente a los datos en el mapa. Hay algunos detalles, pero todo está bien documentado y puede darle una idea del " contenedor concurrente " ;. Dependiendo de sus necesidades, esto podría ser totalmente inapropiado ...

Otros consejos

En general, no es una buena idea que las clases de recopilación ofrezcan seguridad para subprocesos, ya que no pueden saber cómo se están utilizando. Se le servirá mucho mejor implementando sus propios mecanismos de bloqueo en las construcciones de nivel superior que utilizan las colecciones.

El impulso shared_mutex proporcionaría el mejor enfoque de lector único / escritor múltiple para envolver un mapa estándar dadas sus restricciones. No conozco ninguna " preconstruida " implementaciones que combinan estos dos, ya que la tarea es generalmente trivial.

Esto depende de la aplicación a implementar. Un " hilo-seguro " el mapa haría que las llamadas individuales en el mapa sean seguras para subprocesos, pero muchas operaciones deben ser seguras para subprocesos a través de llamadas. La aplicación que usa el mapa debe asociar un mutex con el mapa, y usar ese mutex para coordinar los accesos al mismo.

Intentar crear contenedores seguros para subprocesos fue un error en Java, y sería un error en C ++.

Prueba esta biblioteca

http://www.codeproject.com/KB/threads/lwsync.aspx

Se implementa en un enfoque moderno basado en políticas de c ++.

Aquí hay un corte del enlace para mostrar la idea con el caso 'vector'

typedef lwsync::critical_resource<std::vector<int> > sync_vector_t;
sync_vector_t vec;

// some thread:
{
   // Critical resource can be naturally used with STL containers.
   sync_vector_t::const_accessor vec_access = vec.const_access();
   for(std::vector<int>::const_iterator where = vec_access->begin();
         where != vec_access->end();
         ++where;
        )
   std::cout << *where << std::endl;
}

sync_vector_t::accessor some_vector_action()
{
   sync_vector_t::accessor vec_access = vec.access();
   vec_access->push_back(10);
   return vec_access;
   // Access is escalated from within a some_vector_action() scope
   // So that one can make some other action with vector before it becomes
   // unlocked.
}

{
   sync_vector_t::accessor vec_access = some_vector_action();
   vec_access->push_back(20);
   // Elements 10 and 20 will be placed in vector sequentially.
   // Any other action with vector cannot be processed between those two
   // push_back's.
}

Se me ocurrió esto (que estoy seguro de que se puede mejorar para tomar más de dos argumentos):

template<class T1, class T2>
class combine : public T1, public T2
{
public:

    /// We always need a virtual destructor.
    virtual ~combine() { }
};

Esto te permite hacer:

// Combine an std::mutex and std::map<std::string, std::string> into
// a single instance.
combine<std::mutex, std::map<std::string, std::string>> lockableMap;

// Lock the map within scope to modify the map in a thread-safe way.
{
    // Lock the map.
    std::lock_guard<std::mutex> locked(lockableMap);

    // Modify the map.
    lockableMap["Person 1"] = "Jack";
    lockableMap["Person 2"] = "Jill";
}

Si desea utilizar un std :: recursive_mutex y un std :: set, eso también funcionaría.

Aquí hay una propuesta (por mi parte, un desvergonzado tapón) que envuelve los objetos (incluidos los contenedores STL ) para un acceso seguro a los subprocesos eficiente (

)

https://github.com/isocpp/CppCoreGuidelines/issues/924

  

La idea básica es muy simple. Hay solo unas pocas clases de envoltorio utilizadas para forzar el bloqueo de lectura / escritura y, al mismo tiempo, presentar una vista de const (para solo lectura) o no-const (para leer y escribir) del objeto envuelto.

     

La idea es hacer que el tiempo de compilación sea imposible para acceder de forma incorrecta a un recurso compartido entre subprocesos.

El código de implementación se puede encontrar aquí:

https://github.com/galik/GSL / blob / lockable-objects / include / gsl / gsl_lockable

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top