/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <[email protected]> |
| Twosee <[email protected]> |
+----------------------------------------------------------------------+
*/
#pragma once
#include "swoole_memory.h"
#include <sys/file.h>
#include <system_error>
namespace swoole {
class Lock {
public:
enum Type {
RW_LOCK = 1,
MUTEX = 3,
SPIN_LOCK = 5,
COROUTINE_LOCK = 6,
};
Type get_type() const {
return type_;
}
virtual ~Lock() = default;
virtual int lock(int operation = LOCK_EX, int timeout_msec = -1) = 0;
virtual int unlock() = 0;
protected:
Lock(Type type, bool shared) {
type_ = type;
shared_ = shared;
}
Type type_;
bool shared_;
};
struct MutexImpl;
class Mutex final : public Lock {
MutexImpl *impl;
public:
explicit Mutex(bool shared);
~Mutex() override;
int lock(int operation = LOCK_EX, int timeout_msec = -1) override;
int unlock() override;
};
#ifdef HAVE_RWLOCK
struct RWLockImpl;
class RWLock final : public Lock {
RWLockImpl *impl;
public:
explicit RWLock(bool shared);
~RWLock() override;
int lock(int operation = LOCK_EX, int timeout_msec = -1) override;
int unlock() override;
int lock_rd() {
return lock(LOCK_SH);
}
int lock_wr() {
return lock(LOCK_EX);
}
};
#endif
#ifdef HAVE_SPINLOCK
class SpinLock final : public Lock {
pthread_spinlock_t *impl;
public:
explicit SpinLock(bool shared);
~SpinLock() override;
int lock(int operation = LOCK_EX, int timeout_msec = -1) override;
int unlock() override;
};
#endif
class CoroutineLock final : public Lock {
long cid = 0;
sw_atomic_t *value = nullptr;
void *coroutine = nullptr;
int lock_impl(bool blocking = true);
public:
explicit CoroutineLock(bool shared);
~CoroutineLock() override;
int lock(int operation = LOCK_EX, int timeout_msec = -1) override;
int unlock() override;
};
#if defined(HAVE_PTHREAD_BARRIER) && !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__))
#define SW_USE_PTHREAD_BARRIER
#endif
struct Barrier {
#ifdef SW_USE_PTHREAD_BARRIER
pthread_barrier_t barrier_;
pthread_barrierattr_t barrier_attr_;
bool shared_;
#else
sw_atomic_t count_;
sw_atomic_t barrier_;
#endif
void init(bool shared, int count);
void wait();
void destroy();
};
} // namespace swoole