ZLMediaKit 服务器源码解读---环形数据(RingBuffer)的读写

一:RingBuffer主要的成员变量
    typename RingStorage::Ptr _storage;
    typename RingDelegate<T>::Ptr _delegate;
    onReaderChanged _on_reader_changed;
    unordered_map<EventPoller::Ptr, typename RingReaderDispatcher::Ptr, HashOfPtr> _dispatcher_map;
1.1 _storage

是一个_RingStorage类,存储的容器为list,容器存储的是一帧数据,作用是存储一组GOP数据,遇到I帧则从新缓存
定义如下:

List<pair<bool, T> > _data_cache;
1.2 _delegate

是一个 RingDelegate类,通过setDelegate赋值,代理定义如下,显然RingDelegate是通过onWrite将数据转发出去

template<typename T>
class RingDelegate {
public:
    typedef std::shared_ptr<RingDelegate> Ptr;
    RingDelegate() {}
    virtual ~RingDelegate() {}
    virtual void onWrite(T in, bool is_key = true) = 0;
};
1.3 _dispatcher_map
_dispatcher_map 的申明
unordered_map<EventPoller::Ptr, typename RingReaderDispatcher::Ptr, HashOfPtr> _dispatcher_map;

typedef _RingReaderDispatcher<T> RingReaderDispatcher;
_dispatcher_map 数据的增加

通过attach为_dispatcher_map(RingReaderDispatcher)增加读取类RingReader

std::shared_ptr<RingReader> attach(const EventPoller::Ptr &poller, bool use_cache) {
        if (!poller->isCurrentThread()) {
            throw std::runtime_error("必须在绑定的poller线程中执行attach操作");
        }

        weak_ptr<_RingReaderDispatcher> weakSelf = this->shared_from_this();
        auto on_dealloc = [weakSelf, poller](RingReader *ptr) {
            poller->async([weakSelf, ptr]() {
                auto strongSelf = weakSelf.lock();
                if (strongSelf && strongSelf->_reader_map.erase(ptr)) {
                    --strongSelf->_reader_size;
                    strongSelf->onSizeChanged(false);
                }
                delete ptr;
            });
        };

        std::shared_ptr<RingReader> reader(new RingReader(_storage, use_cache), on_dealloc);
        _reader_map[reader.get()] = std::move(reader);
        ++_reader_size;
        onSizeChanged(true);
        return reader;
    }
_dispatcher_map 数据的读取(分发)

_RingReaderDispatcher里包含了一个键值对_reader_map,分发对象都会存储在这里,定义如下

 unordered_map<void *, std::weak_ptr<RingReader>> _reader_map;

数据读取是通过RingReader去处理

typedef _RingReader<T> RingReader;

_RingReader定义如下,通过onRead调用了_read_cb将数据回调出去,而_read_cb通过setReadCB设置

/**
* 环形缓存读取器
* 该对象的事件触发都会在绑定的poller线程中执行
* 所以把锁去掉了
* 对该对象的一切操作都应该在poller线程中执行
* @tparam T
*/
template<typename T>
class _RingReader {
public:
    void setReadCB(const function<void(const T &)> &cb) {
        if (!cb) {
            _read_cb = [](const T &) {};
        } else {
            _read_cb = cb;
            flushGop();
        }
    }
	......
private:
    void onRead(const T &data, bool is_key) {
        _read_cb(data);
    }
    ......
    void flushGop() {
        if (!_use_cache) {
            return;
        }
        _storage->getCache().for_each([&](const pair<bool, T> &pr) {
            onRead(pr.second, pr.first);
        });
    }
    ......
};
二:数据写入

很显然数据通过遍历_dispatcher_map去处理,最终都是_RingReader去处理,而_RingReader最终数据都会通过_read_cb回调出去

 void write(T in, bool is_key = true) {
 		if (_delegate) {
            _delegate->onWrite(std::move(in), is_key);
            return;
        }
        LOCK_GUARD(_mtx_map);
        for (auto &pr : _dispatcher_map) {
            auto &second = pr.second;
            //切换线程后触发onRead事件
            pr.first->async([second, in, is_key]() {
                second->write(std::move(const_cast<T &>(in)), is_key);
            }, false);
        }
        _storage->write(std::move(in), is_key);
}
总结:

使用RingBuffer时数据通过write写入(这里是异步写入),通过write接口写入数据
通过attach将读取器(_RingReader)添加进RingBuffer的分发map,此时attach接口返回一个RingReader,通过返回的RingReader调用setReadCB设置回调函数将数据拿到


template<typename T>
class RingBuffer : public enable_shared_from_this<RingBuffer<T> > {
public:
    typedef std::shared_ptr<RingBuffer> Ptr;
    typedef _RingReader<T> RingReader;
    typedef _RingStorage<T> RingStorage;
    typedef _RingReaderDispatcher<T> RingReaderDispatcher;
    typedef function<void(int size)> onReaderChanged;

    RingBuffer(int max_size = 1024, const onReaderChanged &cb = nullptr) {
        _on_reader_changed = cb;
        _storage = std::make_shared<RingStorage>(max_size);
    }

    ~RingBuffer() {}

    void write(T in, bool is_key = true);

    
    std::shared_ptr<RingReader> attach(const EventPoller::Ptr &poller, bool use_cache = true);

};
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dai1396734

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值