acid--sync模块

协程同步原语

mutex.h

这个头文件主要用RAII封装了

  • ScopedLock:是一个class template,其拥有一个m_mutex成员变量指向真正的锁,其lock、trylock、unlock都是调用m_mutex对应的函数。下面的Mutex、SpinLock、CoMutex都定义了对应类型的ScopedLock,相当于ScopedLock只是一个外壳。
  • 自旋锁(SpinLock):封装了pthread_spinlock_t
  • 互斥量(Mutex):封装了pthread_mutex_t
  • 读锁(ReadScopedLock)和写锁(WriteScopedLock):拥有一个读写锁(RWMutex)作为成员变量,其lock调用的是读写锁的wlock()和rlock()
  • 读写锁(RWMutex):封装了pthread_rwlock_t

CoMutex 协程锁

class CoMutex : Noncopyable {
public:
    using Lock = ScopedLock<CoMutex>;

    bool tryLock();

    void lock();

    void unlock();
private:
    // 协程所持有的锁
    SpinLock m_mutex;
    // 保护等待队列的锁
    SpinLock m_gaurd;
    // 持有锁的协程id
    uint64_t m_fiberId = 0;
    // 协程等待队列
    std::queue<std::shared_ptr<Fiber>> m_waitQueue;
};
  • lock:调用m_mutex的tryLock尝试获取锁,获取失败就将当前协程加入到协程锁的等待队列并让出协程
  • unlock:从等待队列中取出一个等待协程并重新加入调度

CoCondvar 协程条件变量

co_condvar.h头文件只有一个变量CoCondvar,其封装的接口与std::condition_variable一样:wait、notify、notify_all

class CoCondVar : Noncopyable {
public:
    using MutexType = SpinLock;
    void notify();
    void notifyAll();
    void wait();
    void wait(CoMutex::Lock& lock);

private:
    // 协程等待队列
    std::queue<std::shared_ptr<Fiber>> m_waitQueue;
    // 保护协程等待队列
    MutexType m_mutex;
    // 空任务的定时器,让调度器保持调度
    std::shared_ptr<Timer> m_timer;
};
  • notify:从等待队列中取出一个协程并加入调度
  • notify_all:将等待队列中的所有协程取出并加入调度
  • wait():将当前协程加入到等待队列,并让出协程

CoCountDownLatch 协程计数器

与muduo的CountDownLatch一样

CoSemaphore 协程信号量

co_semaphore.h有两个类

  • Semaphore:RAII封装sem_t。这样可能会阻塞协程从而导致阻塞整个线程
  • CoSemaphore:通过CoCondVar和CoMutex来同步信号量避免阻塞整个线程

Channel 消息通道

与go语言的chan(channel)基本相同,acid的Channel是一个带有缓冲空间大小的Channel。

其实与muduo的BlockedQueue十分相似,但是这里使用的锁和条件变量都是为了协程专门设定的。

channel.h采用Impl设计模式,就是Channel拥有一个std::shared_ptr<ChannelImpl>指针指向ChannelImpl,Channel的所有功能都是调用ChannelImpl完成。

ChannelImpl成员变量如下:

bool m_isClose;
// Channel 缓冲区大小
size_t m_capacity;
// 协程锁和协程条件变量配合使用保护消息队列
CoMutex m_mutex;
// 入队条件变量
CoCondVar m_pushCv;
// 出队条件变量
CoCondVar m_popCv;
// 消息队列
std::queue<T> m_queue;

主要成员函数:

  • push和pop的主要逻辑和阻塞队列一样,不再赘述
  • <<>>分别封装了push和pop,使用方法与go语言一致

而Channel对外暴露的功能都是借助于ChannelImpl实现,不再赘述。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值