es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Intentando hacer referencia a una función eliminada (constructor de copia)

Obtuve este ejemplo de spinlock de Anthony Williams, y hay algo mal en él (o yo tuve un largo día).

#include <atomic>
class spinlock 
{
    std::atomic_flag flag;
public:
    spinlock() : flag(ATOMIC_FLAG_INIT) {}
    void lock() {
        while (flag.test_and_set(std::memory_order_acquire));
    }
    void unlock(){
        flag.clear(std::memory_order_release);
    }
};

spinlock sl;
void f() 
{
    std::lock_guard lc(sl);
}

int main()
{
    f();
}

Entonces, esto es suficiente para que std::lock_guard lo adquiera, pero tengo un error de compilación.

error C2280: ‘std::atomic_flag::atomic_flag(const std::atomic_flag &)’: intentando hacer referencia a una función eliminada

Honestamente, no veo cómo spinlock() : flag(ATOMIC_FLAG_INIT) {} está llamando a un constructor de copia.
Estoy utilizando VS2022 con el estándar C++20 y ATOMICFLAGINIT se define de la siguiente manera:

#define ATOMIC_FLAG_INIT \
    {}

¿Está este ejemplo del libro roto o estoy entendiendo algo mal?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Parece que el ejemplo del libro no está roto, pero el uso de std::lock_guard es incorrecto.

    El problema con el código es que std::lock_guard espera un objeto similar a un mutex con funciones miembro lock() y unlock(), pero spinlock solo tiene funciones lock() y unlock().

    Para solucionar el error, podemos crear un alias de tipo (typedef) para std::lock_guard<spinlock> y usarlo en su lugar:

    #include <atomic>
    class spinlock 
    {
        std::atomic_flag flag;
    public:
        spinlock() : flag(ATOMIC_FLAG_INIT) {}
        void lock() {
            while (flag.test_and_set(std::memory_order_acquire));
        }
        void unlock(){
            flag.clear(std::memory_order_release);
        }
    };
    
    // Define un alias para std::lock_guard
    typedef std::lock_guard<spinlock> spinlock_guard;
    
    spinlock sl;
    void f() 
    {
        spinlock_guard lc(sl);
    }
    
    int main()
    {
        f();
    }
    

    Al utilizar spinlock_guard en lugar de std::lock_guard, podemos adquirir y liberar correctamente el bloqueo sin errores de compilación.

Comments are closed.