1 /* 2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_H_ 12 #define LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_H_ 13 14 #include <stdint.h> 15 16 #include <algorithm> 17 #include <memory> 18 #include <utility> 19 #include <vector> 20 21 #include "api/function_view.h" 22 #include "rtc_base/checks.h" 23 24 namespace webrtc { 25 26 // This file contains helper class used to process the elements of two or more 27 // sorted lists in timestamp order. The effect is the same as doing a merge step 28 // in the merge-sort algorithm but without copying the elements or modifying the 29 // lists. 30 31 namespace event_processor_impl { 32 // Interface to allow "merging" lists of different types. ProcessNext() 33 // processes the next unprocesses element in the list. IsEmpty() checks if all 34 // elements have been processed. GetNextTime returns the timestamp of the next 35 // unprocessed element. 36 class ProcessableEventListInterface { 37 public: 38 virtual ~ProcessableEventListInterface() = default; 39 virtual void ProcessNext() = 0; 40 virtual bool IsEmpty() const = 0; 41 virtual int64_t GetNextTime() const = 0; 42 virtual int GetTieBreaker() const = 0; 43 }; 44 45 // ProcessableEventList encapsulates a list of events and a function that will 46 // be applied to each element of the list. 47 template <typename Iterator, typename T> 48 class ProcessableEventList : public ProcessableEventListInterface { 49 public: ProcessableEventList(Iterator begin,Iterator end,std::function<void (const T &)> f,int tie_breaker)50 ProcessableEventList(Iterator begin, 51 Iterator end, 52 std::function<void(const T&)> f, 53 int tie_breaker) 54 : begin_(begin), end_(end), f_(f), tie_breaker_(tie_breaker) {} 55 ProcessNext()56 void ProcessNext() override { 57 RTC_DCHECK(!IsEmpty()); 58 f_(*begin_); 59 ++begin_; 60 } 61 IsEmpty()62 bool IsEmpty() const override { return begin_ == end_; } 63 GetNextTime()64 int64_t GetNextTime() const override { 65 RTC_DCHECK(!IsEmpty()); 66 return begin_->log_time_us(); 67 } GetTieBreaker()68 int GetTieBreaker() const override { return tie_breaker_; } 69 70 private: 71 Iterator begin_; 72 Iterator end_; 73 std::function<void(const T&)> f_; 74 int tie_breaker_; 75 }; 76 } // namespace event_processor_impl 77 78 // Helper class used to "merge" two or more lists of ordered RtcEventLog events 79 // so that they can be treated as a single ordered list. Since the individual 80 // lists may have different types, we need to access the lists via pointers to 81 // the common base class. 82 // 83 // Usage example: 84 // ParsedRtcEventLogNew log; 85 // auto incoming_handler = [] (LoggedRtcpPacketIncoming elem) { ... }; 86 // auto outgoing_handler = [] (LoggedRtcpPacketOutgoing elem) { ... }; 87 // 88 // RtcEventProcessor processor; 89 // processor.AddEvents(log.incoming_rtcp_packets(), 90 // incoming_handler); 91 // processor.AddEvents(log.outgoing_rtcp_packets(), 92 // outgoing_handler); 93 // processor.ProcessEventsInOrder(); 94 class RtcEventProcessor { 95 public: 96 RtcEventProcessor(); 97 ~RtcEventProcessor(); 98 // The elements of each list is processed in the index order. To process all 99 // elements in all lists in timestamp order, each list needs to be sorted in 100 // timestamp order prior to insertion. 101 // N.B. `iterable` is not owned by RtcEventProcessor. The caller must ensure 102 // that the iterable outlives RtcEventProcessor and it must not be modified 103 // until processing has finished. 104 template <typename Iterable> AddEvents(const Iterable & iterable,std::function<void (const typename Iterable::value_type &)> handler)105 void AddEvents( 106 const Iterable& iterable, 107 std::function<void(const typename Iterable::value_type&)> handler) { 108 if (iterable.begin() == iterable.end()) 109 return; 110 event_lists_.push_back( 111 std::make_unique<event_processor_impl::ProcessableEventList< 112 typename Iterable::const_iterator, typename Iterable::value_type>>( 113 iterable.begin(), iterable.end(), handler, 114 insertion_order_index_++)); 115 std::push_heap(event_lists_.begin(), event_lists_.end(), Cmp); 116 } 117 118 void ProcessEventsInOrder(); 119 120 private: 121 using ListPtrType = 122 std::unique_ptr<event_processor_impl::ProcessableEventListInterface>; 123 int insertion_order_index_ = 0; 124 std::vector<ListPtrType> event_lists_; 125 // Comparison function to make `event_lists_` into a min heap. 126 static bool Cmp(const ListPtrType& a, const ListPtrType& b); 127 }; 128 129 } // namespace webrtc 130 131 #endif // LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_H_ 132