xref: /aosp_15_r20/external/perfetto/src/tracing/internal/tracing_muxer_impl.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SRC_TRACING_INTERNAL_TRACING_MUXER_IMPL_H_
18 #define SRC_TRACING_INTERNAL_TRACING_MUXER_IMPL_H_
19 
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include <array>
24 #include <atomic>
25 #include <bitset>
26 #include <functional>
27 #include <list>
28 #include <map>
29 #include <memory>
30 #include <set>
31 #include <utility>
32 #include <vector>
33 
34 #include "perfetto/base/time.h"
35 #include "perfetto/ext/base/scoped_file.h"
36 #include "perfetto/ext/base/thread_checker.h"
37 #include "perfetto/ext/tracing/core/basic_types.h"
38 #include "perfetto/ext/tracing/core/consumer.h"
39 #include "perfetto/ext/tracing/core/producer.h"
40 #include "perfetto/ext/tracing/core/tracing_service.h"
41 #include "perfetto/tracing/backend_type.h"
42 #include "perfetto/tracing/core/data_source_descriptor.h"
43 #include "perfetto/tracing/core/forward_decls.h"
44 #include "perfetto/tracing/core/trace_config.h"
45 #include "perfetto/tracing/internal/basic_types.h"
46 #include "perfetto/tracing/internal/tracing_muxer.h"
47 #include "perfetto/tracing/tracing.h"
48 
49 #include "protos/perfetto/common/interceptor_descriptor.gen.h"
50 
51 namespace perfetto {
52 
53 class ConsumerEndpoint;
54 class DataSourceBase;
55 class ProducerEndpoint;
56 class TraceWriterBase;
57 class TracingBackend;
58 class TracingSession;
59 struct TracingInitArgs;
60 
61 namespace base {
62 class TaskRunner;
63 }
64 
65 namespace shlib {
66 void ResetForTesting();
67 }
68 
69 namespace test {
70 class TracingMuxerImplInternalsForTest;
71 }
72 
73 namespace internal {
74 
75 struct DataSourceStaticState;
76 
77 // This class acts as a bridge between the public API and the TracingBackend(s).
78 // It exposes a simplified view of the world to the API methods handling all the
79 // bookkeeping to map data source instances and trace writers to the various
80 // backends. It deals with N data sources, M backends (1 backend == 1 tracing
81 // service == 1 producer connection) and T concurrent tracing sessions.
82 //
83 // Handing data source registration and start/stop flows [producer side]:
84 // ----------------------------------------------------------------------
85 // 1. The API client subclasses perfetto::DataSource and calls
86 //    DataSource::Register<MyDataSource>(). In turn this calls into the
87 //    TracingMuxer.
88 // 2. The tracing muxer iterates through all the backends (1 backend == 1
89 //    service == 1 producer connection) and registers the data source on each
90 //    backend.
91 // 3. When any (services behind a) backend starts tracing and requests to start
92 //    that specific data source, the TracingMuxerImpl constructs a new instance
93 //    of MyDataSource and calls the OnStart() method.
94 //
95 // Controlling trace and retrieving trace data [consumer side]:
96 // ------------------------------------------------------------
97 // 1. The API client calls Tracing::NewTrace(), returns a RAII TracingSession
98 //    object.
99 // 2. NewTrace() calls into internal::TracingMuxer(Impl). TracingMuxer
100 //    subclasses the TracingSession object (TracingSessionImpl) and returns it.
101 // 3. The tracing muxer identifies the backend (according to the args passed to
102 //    NewTrace), creates a new Consumer and connects to it.
103 // 4. When the API client calls Start()/Stop()/ReadTrace() methods, the
104 //    TracingMuxer forwards them to the consumer associated to the
105 //    TracingSession. Likewise for callbacks coming from the consumer-side of
106 //    the service.
107 class TracingMuxerImpl : public TracingMuxer {
108  public:
109   // This is different than TracingSessionID because it's global across all
110   // backends. TracingSessionID is global only within the scope of one service.
111   using TracingSessionGlobalID = uint64_t;
112 
113   struct RegisteredDataSource {
114     DataSourceDescriptor descriptor;
115     DataSourceFactory factory{};
116     bool supports_multiple_instances = false;
117     bool requires_callbacks_under_lock = false;
118     bool no_flush = false;
119     DataSourceStaticState* static_state = nullptr;
120   };
121 
122   static void InitializeInstance(const TracingInitArgs&);
123   static void ResetForTesting();
124   static void Shutdown();
125 
126   // TracingMuxer implementation.
127   bool RegisterDataSource(const DataSourceDescriptor&,
128                           DataSourceFactory,
129                           DataSourceParams,
130                           bool no_flush,
131                           DataSourceStaticState*) override;
132   void UpdateDataSourceDescriptor(const DataSourceDescriptor&,
133                                   const DataSourceStaticState*) override;
134   std::unique_ptr<TraceWriterBase> CreateTraceWriter(
135       DataSourceStaticState*,
136       uint32_t data_source_instance_index,
137       DataSourceState*,
138       BufferExhaustedPolicy buffer_exhausted_policy) override;
139   void DestroyStoppedTraceWritersForCurrentThread() override;
140   void RegisterInterceptor(const InterceptorDescriptor&,
141                            InterceptorFactory,
142                            InterceptorBase::TLSFactory,
143                            InterceptorBase::TracePacketCallback) override;
144 
145   void ActivateTriggers(const std::vector<std::string>&, uint32_t) override;
146 
147   std::unique_ptr<TracingSession> CreateTracingSession(
148       BackendType,
149       TracingConsumerBackend* (*system_backend_factory)());
150   std::unique_ptr<StartupTracingSession> CreateStartupTracingSession(
151       const TraceConfig& config,
152       Tracing::SetupStartupTracingOpts);
153   std::unique_ptr<StartupTracingSession> CreateStartupTracingSessionBlocking(
154       const TraceConfig& config,
155       Tracing::SetupStartupTracingOpts);
156 
157   // Producer-side bookkeeping methods.
158   void UpdateDataSourcesOnAllBackends();
159   void SetupDataSource(TracingBackendId,
160                        uint32_t backend_connection_id,
161                        DataSourceInstanceID,
162                        const DataSourceConfig&);
163   void StartDataSource(TracingBackendId, DataSourceInstanceID);
164   void StopDataSource_AsyncBegin(TracingBackendId, DataSourceInstanceID);
165   void ClearDataSourceIncrementalState(TracingBackendId, DataSourceInstanceID);
166   void SyncProducersForTesting();
167 
168   // Consumer-side bookkeeping methods.
169   void SetupTracingSession(TracingSessionGlobalID,
170                            const std::shared_ptr<TraceConfig>&,
171                            base::ScopedFile trace_fd = base::ScopedFile());
172   void StartTracingSession(TracingSessionGlobalID);
173   void CloneTracingSession(TracingSessionGlobalID,
174                            TracingSession::CloneTraceArgs,
175                            TracingSession::CloneTraceCallback);
176   void ChangeTracingSessionConfig(TracingSessionGlobalID, const TraceConfig&);
177   void StopTracingSession(TracingSessionGlobalID);
178   void DestroyTracingSession(TracingSessionGlobalID);
179   void FlushTracingSession(TracingSessionGlobalID,
180                            uint32_t,
181                            std::function<void(bool)>);
182   void ReadTracingSessionData(
183       TracingSessionGlobalID,
184       std::function<void(TracingSession::ReadTraceCallbackArgs)>);
185   void GetTraceStats(TracingSessionGlobalID,
186                      TracingSession::GetTraceStatsCallback);
187   void QueryServiceState(TracingSessionGlobalID,
188                          TracingSession::QueryServiceStateCallback);
189 
190   // Sets the batching period to |batch_commits_duration_ms| on the backends
191   // with type |backend_type|.
192   void SetBatchCommitsDurationForTesting(uint32_t batch_commits_duration_ms,
193                                          BackendType backend_type);
194 
195   // Enables direct SMB patching on the backends with type |backend_type| (see
196   // SharedMemoryArbiter::EnableDirectSMBPatching). Returns true if the
197   // operation succeeded for all backends with type |backend_type|, false
198   // otherwise.
199   bool EnableDirectSMBPatchingForTesting(BackendType backend_type);
200 
201   void SetMaxProducerReconnectionsForTesting(uint32_t count);
202 
203  private:
204   friend class test::TracingMuxerImplInternalsForTest;
205   friend void shlib::ResetForTesting();
206 
207   // For each TracingBackend we create and register one ProducerImpl instance.
208   // This talks to the producer-side of the service, gets start/stop requests
209   // from it and routes them to the registered data sources.
210   // One ProducerImpl == one backend == one tracing service.
211   // This class is needed to disambiguate callbacks coming from different
212   // services. TracingMuxerImpl can't directly implement the Producer interface
213   // because the Producer virtual methods don't allow to identify the service.
214   class ProducerImpl : public Producer {
215    public:
216     ProducerImpl(TracingMuxerImpl*,
217                  TracingBackendId,
218                  uint32_t shmem_batch_commits_duration_ms,
219                  bool shmem_direct_patching_enabled);
220     ~ProducerImpl() override;
221 
222     void Initialize(std::unique_ptr<ProducerEndpoint> endpoint);
223     void RegisterDataSource(const DataSourceDescriptor&,
224                             DataSourceFactory,
225                             DataSourceStaticState*);
226     void DisposeConnection();
227 
228     // perfetto::Producer implementation.
229     void OnConnect() override;
230     void OnDisconnect() override;
231     void OnTracingSetup() override;
232     void OnStartupTracingSetup() override;
233     void SetupDataSource(DataSourceInstanceID,
234                          const DataSourceConfig&) override;
235     void StartDataSource(DataSourceInstanceID,
236                          const DataSourceConfig&) override;
237     void StopDataSource(DataSourceInstanceID) override;
238     void Flush(FlushRequestID,
239                const DataSourceInstanceID*,
240                size_t,
241                FlushFlags) override;
242     void ClearIncrementalState(const DataSourceInstanceID*, size_t) override;
243 
244     bool SweepDeadServices();
245     void SendOnConnectTriggers();
246     void NotifyFlushForDataSourceDone(DataSourceInstanceID, FlushRequestID);
247 
248     PERFETTO_THREAD_CHECKER(thread_checker_)
249     TracingMuxerImpl* muxer_;
250     TracingBackendId const backend_id_;
251     bool connected_ = false;
252     bool did_setup_tracing_ = false;
253     bool did_setup_startup_tracing_ = false;
254     std::atomic<uint32_t> connection_id_{0};
255     uint16_t last_startup_target_buffer_reservation_ = 0;
256     bool is_producer_provided_smb_ = false;
257     bool producer_provided_smb_failed_ = false;
258 
259     const uint32_t shmem_batch_commits_duration_ms_ = 0;
260     const bool shmem_direct_patching_enabled_ = false;
261 
262     // Set of data sources that have been actually registered on this producer.
263     // This can be a subset of the global |data_sources_|, because data sources
264     // can register before the producer is fully connected.
265     std::bitset<kMaxDataSources> registered_data_sources_{};
266 
267     // A collection of disconnected service endpoints. Since trace writers on
268     // arbitrary threads might continue writing data to disconnected services,
269     // we keep the old services around and periodically try to clean up ones
270     // that no longer have any writers (see SweepDeadServices).
271     std::list<std::shared_ptr<ProducerEndpoint>> dead_services_;
272 
273     // Triggers that should be sent when the service connects (trigger_name,
274     // expiration).
275     std::list<std::pair<std::string, base::TimeMillis>> on_connect_triggers_;
276 
277     std::map<FlushRequestID, std::set<DataSourceInstanceID>> pending_flushes_;
278 
279     // The currently active service endpoint is maintained as an atomic shared
280     // pointer so it won't get deleted from underneath threads that are creating
281     // trace writers. At any given time one endpoint can be shared (and thus
282     // kept alive) by the |service_| pointer, an entry in |dead_services_| and
283     // as a pointer on the stack in CreateTraceWriter() (on an arbitrary
284     // thread). The endpoint is never shared outside ProducerImpl itself.
285     //
286     // WARNING: Any *write* access to this variable or any *read* access from a
287     // non-muxer thread must be done through std::atomic_{load,store} to avoid
288     // data races.
289     std::shared_ptr<ProducerEndpoint> service_;  // Keep last.
290   };
291 
292   // For each TracingSession created by the API client (Tracing::NewTrace() we
293   // create and register one ConsumerImpl instance.
294   // This talks to the consumer-side of the service, gets end-of-trace and
295   // on-trace-data callbacks and routes them to the API client callbacks.
296   // This class is needed to disambiguate callbacks coming from different
297   // tracing sessions.
298   class ConsumerImpl : public Consumer {
299    public:
300     ConsumerImpl(TracingMuxerImpl*, BackendType, TracingSessionGlobalID);
301     ~ConsumerImpl() override;
302 
303     void Initialize(std::unique_ptr<ConsumerEndpoint> endpoint);
304 
305     // perfetto::Consumer implementation.
306     void OnConnect() override;
307     void OnDisconnect() override;
308     void OnTracingDisabled(const std::string& error) override;
309     void OnTraceData(std::vector<TracePacket>, bool has_more) override;
310     void OnDetach(bool success) override;
311     void OnAttach(bool success, const TraceConfig&) override;
312     void OnTraceStats(bool success, const TraceStats&) override;
313     void OnObservableEvents(const ObservableEvents&) override;
314     void OnSessionCloned(const OnSessionClonedArgs&) override;
315 
316     void NotifyStartComplete();
317     void NotifyError(const TracingError&);
318     void NotifyStopComplete();
319 
320     // Will eventually inform the |muxer_| when it is safe to remove |this|.
321     void Disconnect();
322 
323     TracingMuxerImpl* muxer_;
324     BackendType const backend_type_;
325     TracingSessionGlobalID const session_id_;
326     bool connected_ = false;
327 
328     // This is to handle the case where the Setup call from the API client
329     // arrives before the consumer has connected. In this case we keep around
330     // the config and check if we have it after connection.
331     bool start_pending_ = false;
332 
333     // Similarly if the session is stopped before the consumer was connected, we
334     // need to wait until the session has started before stopping it.
335     bool stop_pending_ = false;
336 
337     // Similarly we need to buffer a call to get trace statistics if the
338     // consumer wasn't connected yet.
339     bool get_trace_stats_pending_ = false;
340 
341     // Similarly we need to buffer a session cloning args if the session is
342     // cloning another sesison before the consumer was connected.
343     std::optional<ConsumerEndpoint::CloneSessionArgs> session_to_clone_;
344 
345     // Whether this session was already stopped. This will happen in response to
346     // Stop{,Blocking}, but also if the service stops the session for us
347     // automatically (e.g., when there are no data sources).
348     bool stopped_ = false;
349 
350     // shared_ptr because it's posted across threads. This is to avoid copying
351     // it more than once.
352     std::shared_ptr<TraceConfig> trace_config_;
353     base::ScopedFile trace_fd_;
354 
355     // If the API client passes a callback to start, we should invoke this when
356     // NotifyStartComplete() is invoked.
357     std::function<void()> start_complete_callback_;
358 
359     // An internal callback used to implement StartBlocking().
360     std::function<void()> blocking_start_complete_callback_;
361 
362     // If the API client passes a callback to get notification about the
363     // errors, we should invoke this when NotifyError() is invoked.
364     std::function<void(TracingError)> error_callback_;
365 
366     // If the API client passes a callback to stop, we should invoke this when
367     // OnTracingDisabled() is invoked.
368     std::function<void()> stop_complete_callback_;
369 
370     // An internal callback used to implement StopBlocking().
371     std::function<void()> blocking_stop_complete_callback_;
372 
373     // Callback for a pending call to CloneTrace().
374     TracingSession::CloneTraceCallback clone_trace_callback_;
375 
376     // Callback passed to ReadTrace().
377     std::function<void(TracingSession::ReadTraceCallbackArgs)>
378         read_trace_callback_;
379 
380     // Callback passed to GetTraceStats().
381     TracingSession::GetTraceStatsCallback get_trace_stats_callback_;
382 
383     // Callback for a pending call to QueryServiceState().
384     TracingSession::QueryServiceStateCallback query_service_state_callback_;
385 
386     // The states of all data sources in this tracing session. |true| means the
387     // data source has started tracing.
388     using DataSourceHandle = std::pair<std::string, std::string>;
389     std::map<DataSourceHandle, bool> data_source_states_;
390 
391     std::unique_ptr<ConsumerEndpoint> service_;  // Keep before last.
392     PERFETTO_THREAD_CHECKER(thread_checker_)     // Keep last.
393   };
394 
395   // This object is returned to API clients when they call
396   // Tracing::CreateTracingSession().
397   class TracingSessionImpl : public TracingSession {
398    public:
399     TracingSessionImpl(TracingMuxerImpl*, TracingSessionGlobalID, BackendType);
400     ~TracingSessionImpl() override;
401     void Setup(const TraceConfig&, int fd) override;
402     void Start() override;
403     void StartBlocking() override;
404     void CloneTrace(CloneTraceArgs args, CloneTraceCallback) override;
405     void SetOnStartCallback(std::function<void()>) override;
406     void SetOnErrorCallback(std::function<void(TracingError)>) override;
407     void Stop() override;
408     void StopBlocking() override;
409     void Flush(std::function<void(bool)>, uint32_t timeout_ms) override;
410     void ReadTrace(ReadTraceCallback) override;
411     void SetOnStopCallback(std::function<void()>) override;
412     void GetTraceStats(GetTraceStatsCallback) override;
413     void QueryServiceState(QueryServiceStateCallback) override;
414     void ChangeTraceConfig(const TraceConfig&) override;
415 
416    private:
417     TracingMuxerImpl* const muxer_;
418     TracingSessionGlobalID const session_id_;
419     BackendType const backend_type_;
420   };
421 
422   // This object is returned to API clients when they call
423   // Tracing::SetupStartupTracing().
424   class StartupTracingSessionImpl : public StartupTracingSession {
425    public:
426     StartupTracingSessionImpl(TracingMuxerImpl*,
427                               TracingSessionGlobalID,
428                               BackendType);
429     ~StartupTracingSessionImpl() override;
430     void Abort() override;
431     void AbortBlocking() override;
432 
433    private:
434     TracingMuxerImpl* const muxer_;
435     TracingSessionGlobalID const session_id_;
436     BackendType backend_type_;
437   };
438 
439   struct RegisteredInterceptor {
440     protos::gen::InterceptorDescriptor descriptor;
441     InterceptorFactory factory{};
442     InterceptorBase::TLSFactory tls_factory{};
443     InterceptorBase::TracePacketCallback packet_callback{};
444   };
445 
446   struct RegisteredStartupSession {
447     TracingSessionID session_id = 0;
448     int num_unbound_data_sources = 0;
449 
450     bool is_aborting = false;
451     int num_aborting_data_sources = 0;
452 
453     std::function<void()> on_aborted;
454     std::function<void()> on_adopted;
455   };
456 
457   struct RegisteredProducerBackend {
458     // Backends are supposed to have static lifetime.
459     TracingProducerBackend* backend = nullptr;
460     TracingBackendId id = 0;
461     BackendType type{};
462 
463     TracingBackend::ConnectProducerArgs producer_conn_args;
464     std::unique_ptr<ProducerImpl> producer;
465 
466     std::vector<RegisteredStartupSession> startup_sessions;
467   };
468 
469   struct RegisteredConsumerBackend {
470     // Backends are supposed to have static lifetime.
471     TracingConsumerBackend* backend = nullptr;
472     BackendType type{};
473     // The calling code can request more than one concurrently active tracing
474     // session for the same backend. We need to create one consumer per session.
475     std::vector<std::unique_ptr<ConsumerImpl>> consumers;
476   };
477 
478   void UpdateDataSourceOnAllBackends(RegisteredDataSource& rds,
479                                      bool is_changed);
480   explicit TracingMuxerImpl(const TracingInitArgs&);
481   void Initialize(const TracingInitArgs& args);
482   void AddBackends(const TracingInitArgs& args);
483   void AddConsumerBackend(TracingConsumerBackend* backend, BackendType type);
484   void AddProducerBackend(TracingProducerBackend* backend,
485                           BackendType type,
486                           const TracingInitArgs& args);
487   ConsumerImpl* FindConsumer(TracingSessionGlobalID session_id);
488   std::pair<ConsumerImpl*, RegisteredConsumerBackend*> FindConsumerAndBackend(
489       TracingSessionGlobalID session_id);
490   RegisteredProducerBackend* FindProducerBackendById(TracingBackendId id);
491   RegisteredProducerBackend* FindProducerBackendByType(BackendType type);
492   RegisteredConsumerBackend* FindConsumerBackendByType(BackendType type);
493   void InitializeConsumer(TracingSessionGlobalID session_id);
494   void OnConsumerDisconnected(ConsumerImpl* consumer);
495   void OnProducerDisconnected(ProducerImpl* producer);
496   // Test only method.
497   void SweepDeadBackends();
498 
499   struct FindDataSourceRes {
500     FindDataSourceRes() = default;
FindDataSourceResFindDataSourceRes501     FindDataSourceRes(DataSourceStaticState* a,
502                       DataSourceState* b,
503                       uint32_t c,
504                       bool d)
505         : static_state(a),
506           internal_state(b),
507           instance_idx(c),
508           requires_callbacks_under_lock(d) {}
509     explicit operator bool() const { return !!internal_state; }
510 
511     DataSourceStaticState* static_state = nullptr;
512     DataSourceState* internal_state = nullptr;
513     uint32_t instance_idx = 0;
514     bool requires_callbacks_under_lock = false;
515   };
516   FindDataSourceRes FindDataSource(TracingBackendId, DataSourceInstanceID);
517 
518   FindDataSourceRes SetupDataSourceImpl(
519       const RegisteredDataSource&,
520       TracingBackendId,
521       uint32_t backend_connection_id,
522       DataSourceInstanceID,
523       const DataSourceConfig&,
524       TracingSessionGlobalID startup_session_id);
525   void StartDataSourceImpl(const FindDataSourceRes&);
526   void StopDataSource_AsyncBeginImpl(const FindDataSourceRes&);
527   void StopDataSource_AsyncEnd(TracingBackendId,
528                                uint32_t backend_connection_id,
529                                DataSourceInstanceID,
530                                const FindDataSourceRes&);
531   bool FlushDataSource_AsyncBegin(TracingBackendId,
532                                   DataSourceInstanceID,
533                                   FlushRequestID,
534                                   FlushFlags);
535   void FlushDataSource_AsyncEnd(TracingBackendId,
536                                 uint32_t backend_connection_id,
537                                 DataSourceInstanceID,
538                                 const FindDataSourceRes&,
539                                 FlushRequestID);
540   void AbortStartupTracingSession(TracingSessionGlobalID, BackendType);
541   // When ResetForTesting() is executed, `cb` will be called on the calling
542   // thread and on the muxer thread.
543   void AppendResetForTestingCallback(std::function<void()> cb);
544 
545   // WARNING: If you add new state here, be sure to update ResetForTesting.
546   std::unique_ptr<base::TaskRunner> task_runner_;
547   std::vector<RegisteredDataSource> data_sources_;
548   // These lists can only have one backend per BackendType. The elements are
549   // sorted by BackendType priority (see BackendTypePriority). They always
550   // contain a fake low-priority kUnspecifiedBackend at the end.
551   std::list<RegisteredProducerBackend> producer_backends_;
552   std::list<RegisteredConsumerBackend> consumer_backends_;
553   std::vector<RegisteredInterceptor> interceptors_;
554   TracingPolicy* policy_ = nullptr;
555 
556   // Learn more at TracingInitArgs::supports_multiple_data_source_instances
557   bool supports_multiple_data_source_instances_ = true;
558 
559   std::atomic<TracingSessionGlobalID> next_tracing_session_id_{};
560   std::atomic<uint32_t> next_data_source_index_{};
561   uint32_t muxer_id_for_testing_{};
562 
563   // Maximum number of times we will try to reconnect producer backend.
564   // Should only be modified for testing purposes.
565   std::atomic<uint32_t> max_producer_reconnections_{100u};
566 
567   // Test only member.
568   // After ResetForTesting() is called, holds tracing backends which needs to be
569   // kept alive until all inbound references have gone away. See
570   // SweepDeadBackends().
571   std::list<RegisteredProducerBackend> dead_backends_;
572 
573   // Test only member.
574   // Executes these cleanup functions on the calling thread and on the muxer
575   // thread when ResetForTesting() is called.
576   std::list<std::function<void()>> reset_callbacks_;
577 
578   PERFETTO_THREAD_CHECKER(thread_checker_)
579 };
580 
581 }  // namespace internal
582 }  // namespace perfetto
583 
584 #endif  // SRC_TRACING_INTERNAL_TRACING_MUXER_IMPL_H_
585