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);

};

猜你喜欢

转载自blog.csdn.net/dai1396734/article/details/122827247