File: connection_group.h

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (119 lines) | stat: -rw-r--r-- 4,312 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_GROUP_H_
#define MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_GROUP_H_

#include <atomic>

#include "base/component_export.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/task/sequenced_task_runner.h"

namespace mojo {

// A ConnectionGroup is used to loosely track groups of related interface
// receivers. Any Receiver or PendingReceiver can reference a single
// ConnectionGroup by holding onto a corresponding Ref.
//
// Belonging to a connection group is a viral property: if a Receiver belongs to
// a connection group, any PendingReceivers arriving in inbound messages
// automatically inherit a Ref to the same group. Likewise if a PendingReceiver
// belongs to a group, any Receiver which consumes and binds that
// PendingReceiver inherits its group membership.
class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) ConnectionGroup
    : public base::RefCountedThreadSafe<ConnectionGroup> {
 public:
  // A single opaque reference to a ConnectionGroup. May be freely moved and
  // copied.
  class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) Ref {
   public:
    Ref();
    Ref(const Ref&);
    Ref(Ref&&) noexcept;
    ~Ref();

    Ref& operator=(const Ref&);
    Ref& operator=(Ref&&) noexcept;

    explicit operator bool() const { return group_ != nullptr; }
    void reset();

    // Returns a real reference to the underlying ConnectionGroup. Should only
    // be used in testing.
    scoped_refptr<ConnectionGroup> GetGroupForTesting() { return group_; }

    // Returns a weak copy of this Ref. Does not increase ref-count.
    Ref WeakCopy() const;

    // Indicates whether the underlying ConnectionGroup has zero strong
    // references. Must ONLY be called from the sequence which owns the
    // primordial weak Ref, since that sequence may increase the ref count at
    // any time and otherwise this accessor would be unreliable.
    bool HasZeroRefs() const;

    // Attaches this group to another group, causing the former to retain a
    // reference to the latter throughout its lifetime.
    void SetParentGroup(Ref parent_group);

   private:
    friend class ConnectionGroup;

    enum class Type {
      // A weak Ref does not influence the ref-count of its referenced group.
      // Weak references always produce strong references when copied.
      kWeak,

      // A strong Ref influences the ref-count of its reference group.
      kStrong,
    };

    explicit Ref(scoped_refptr<ConnectionGroup> group);

    Type type_ = Type::kWeak;
    scoped_refptr<ConnectionGroup> group_;
  };

  // Constructs a new ConnectionGroup and returns an initial Ref to it. This
  // initial reference does *not* increase the group's ref-count. All other
  // copies of Ref increase the ref-count. Any time the ref-count is decremented
  // to zero, |callback| is invoked on |task_runner|. If |task_runner| is null
  // (useless except perhaps in tests), |callback| is ignored.
  static Ref Create(base::RepeatingClosure callback,
                    scoped_refptr<base::SequencedTaskRunner> task_runner);

  ConnectionGroup(const ConnectionGroup&) = delete;
  ConnectionGroup& operator=(const ConnectionGroup&) = delete;

  unsigned int GetNumRefsForTesting() const { return num_refs_; }

 private:
  friend class base::RefCountedThreadSafe<ConnectionGroup>;
  friend class Ref;

  ConnectionGroup(base::RepeatingClosure callback,
                  scoped_refptr<base::SequencedTaskRunner> task_runner);

  virtual ~ConnectionGroup();

  void AddGroupRef();
  void ReleaseGroupRef();
  void SetParentGroup(Ref parent_group);

  const base::RepeatingClosure notification_callback_;
  const scoped_refptr<base::SequencedTaskRunner> notification_task_runner_;

  // A reference to this group's parent group, if any.
  Ref parent_group_;

  // We maintain our own ref count because we need to trigger behavior on
  // release, and doing that in conjunction with the RefCountedThreadSafe's own
  // lifetime-controlling ref count is not safely possible.
  std::atomic<unsigned int> num_refs_{0};
};

}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_GROUP_H_