#pragma once

#ifndef SPINLOCK_H_F2918131_13EC_4f01_A797_55061EE3EE64
#define SPINLOCK_H_F2918131_13EC_4f01_A797_55061EE3EE64

#include <pthread.h>
#include <errno.h>
#include "wmc_assert.h"

#include <util/generic/noncopyable.h>

namespace NWebmaster {
namespace threads {

class spinlock : public TNonCopyable {
public:
    spinlock() {
        WMC_CHECK(!pthread_spin_init(&m, 0), "SpinLock can't be created. " + ToString(errno) + " " + ToString(strerror(errno)));
    }
    ~spinlock() {
        WMC_CHECK(!pthread_spin_destroy(&m), "SpinLock can't be destroyed. " + ToString(errno) + " " + ToString(strerror(errno)));
    }

    void lock() {
        WMC_CHECK(!pthread_spin_lock(&m), "SpinLock can't be locked. " + ToString(errno) + " " + ToString(strerror(errno)));
    }

    void unlock() {
        WMC_CHECK(!pthread_spin_unlock(&m), "SpinLock can't be unlocked. " + ToString(errno) + " " + ToString(strerror(errno)));
    }

    bool try_lock() {
        const int res = pthread_spin_trylock(&m);
        WMC_CHECK(!(res && (EBUSY != res)), "SpinLock try_lock return error. " + ToString(errno) + " " + ToString(strerror(errno)));
        return !res;
    }

private:
    pthread_spinlock_t m;
};

} //threads
} //namespace NWebmaster

#endif //SPINLOCK_H_F2918131_13EC_4f01_A797_55061EE3EE64
