xref: /aosp_15_r20/external/webrtc/logging/rtc_event_log/rtc_event_processor.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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