Implementación de una clase singleton con los miembros atómicos

stanislas.b:

Estoy tratando de implementar una clase para realizar un seguimiento de las actuaciones de un código multiproceso y estoy corriendo en el problema siguiente.

El rastreador debe tener una única instancia, por lo tanto el patrón singleton. Con el fin de contar con la creación de objetos y la ejecución de la función al otro lado de todos los hilos, pensé que el uso de miembro atómica sería una idea buena. Pero me parece que no puede encontrar una aplicación correcta.

Se trata de un código mínimo de lo que la varita que hacer:

#include <atomic>
#include <iostream>

class Counter
{
public:
    static Counter& instance()
    {
        return instance_;
    };

    void increment()
    {
        counter_++;
    };

private:
    Counter ()
    {
        std::cout << "ctor counter" << std::endl;
    };

    ~Counter ()
    {
        std::cout << "counter_: " << counter_ << std::endl;
        std::cout << "dtor counter" << std::endl;
    }

    static Counter instance_;
    std::atomic<int> counter_{0};
    //int counter_ = 0;
};

Counter Counter::instance_ = Counter();

int main(void)
{
    Counter::instance().increment();
    Counter::instance().increment();
    Counter::instance().increment();

    return 0;
}

Si la counter_variable es una int, que funciona bien, pero no sería seguro hilo. Si se trata de una atomic<int>, entonces el compilador me dice esto:

   g++ foo.cc
foo.cc:34:38: error: use of deleted function 'Counter::Counter(const Counter&)'
 Counter Counter::instance_ = Counter();
                                      ^
foo.cc:4:7: note: 'Counter::Counter(const Counter&)' is implicitly deleted because the default definition would be ill-formed:
 class Counter
       ^~~~~~~
foo.cc:4:7: error: use of deleted function 'std::atomic<int>::atomic(const std::atomic<int>&)'
In file included from foo.cc:1:0:
/usr/include/c++/7/atomic:668:7: note: declared here
       atomic(const atomic&) = delete;
       ^~~~~~

No estoy seguro de que me acabo de entender el problema. Cualquier explicación / solución sería muy apreciada.

Salud

Peter Cordes:

Se podría simplificar por tener std::atomic<int> counter_{0};simplemente un staticmiembro de la clase en lugar de parte de cada instancia. (Puesto que usted está asegurando que sólo hay una instancia de la clase.)

O si sólo está utilizando su "Singleton" de esa manera devolver una referencia a un objeto estático, simplemente hacer que todos sus miembros staticpor lo que no es necesario ni siquiera obtener un puntero a esa única instancia de ella en el primer lugar. Entonces, sólo puede ser un glorificado namespace{}con funciones miembro estáticas públicas y privadas. Creo que el único punto de un "Singleton" es retrasar la inicialización hasta después de la inicialización estática mediante el uso de una función estática de ámbito con un inicializador no constante, pero que no está haciendo eso.


El problema real es en el constructor copia de la clase, que su inicializador estático utiliza la forma en que has escrito. Se construye un carácter temporal Counter();y luego lo copia en estática instance_variable.

Se puede compilar como C ++ 17, donde elidiendo de dicha copia está garantizada ( obras en Godbolt con g ++ -std=gnu++17con su fuente intacta ), o se puede reescribir el inicializador

Counter Counter::instance_;    // default construct
Counter Counter::instance_{};  // explicitly default construct

Ambos de los trabajos con g ++-std=gnu++11

Supongo que te gusta

Origin http://10.200.1.11:23101/article/api/json?id=406567&siteId=1
Recomendado
Clasificación