summaryrefslogtreecommitdiffstats
path: root/dom/clients/manager/ClientThing.h
blob: 9b2bfcc52d3d87cf4e530eb16d360794e716ab91 (plain)
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _mozilla_dom_ClientThing_h
#define _mozilla_dom_ClientThing_h

#include "nsTArray.h"

namespace mozilla::dom {

// Base class representing various Client "things" such as ClientHandle,
// ClientSource, and ClientManager.  Currently it provides a common set
// of code for handling activation and shutdown of IPC actors.
template <typename ActorType>
class ClientThing {
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
  static const uint32_t kMagic1 = 0xC9FE2C9C;
  static const uint32_t kMagic2 = 0x832072D4;
#endif

  ActorType* mActor;
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
  uint32_t mMagic1;
  uint32_t mMagic2;
#endif
  bool mShutdown;

 protected:
  ClientThing()
      : mActor(nullptr)
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
        ,
        mMagic1(kMagic1),
        mMagic2(kMagic2)
#endif
        ,
        mShutdown(false) {
  }

  ~ClientThing() {
    AssertIsValid();
    ShutdownThing();
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
    mMagic1 = 0;
    mMagic2 = 0;
#endif
  }

  void AssertIsValid() const {
    MOZ_DIAGNOSTIC_ASSERT(mMagic1 == kMagic1);
    MOZ_DIAGNOSTIC_ASSERT(mMagic2 == kMagic2);
  }

  // Return the current actor.
  ActorType* GetActor() const {
    AssertIsValid();
    return mActor;
  }

  // Returns true if ShutdownThing() has been called.
  bool IsShutdown() const {
    AssertIsValid();
    return mShutdown;
  }

  // Conditionally execute the given callable based on the current state.
  template <typename Callable>
  void MaybeExecute(
      const Callable& aSuccess, const std::function<void()>& aFailure = [] {}) {
    AssertIsValid();
    if (mShutdown) {
      aFailure();
      return;
    }
    MOZ_DIAGNOSTIC_ASSERT(mActor);
    aSuccess(mActor);
  }

  // Attach activate the thing by attaching its underlying IPC actor.  This
  // will make the thing register as the actor's owner as well.  The actor
  // must call RevokeActor() to clear this weak back reference before its
  // destroyed.
  void ActivateThing(ActorType* aActor) {
    AssertIsValid();
    MOZ_DIAGNOSTIC_ASSERT(aActor);
    MOZ_DIAGNOSTIC_ASSERT(!mActor);
    MOZ_DIAGNOSTIC_ASSERT(!mShutdown);
    mActor = aActor;
    mActor->SetOwner(this);
  }

  // Start destroying the underlying actor and disconnect the thing.
  void ShutdownThing() {
    AssertIsValid();
    if (mShutdown) {
      return;
    }
    mShutdown = true;

    // If we are shutdown before the actor, then clear the weak references
    // between the actor and the thing.
    if (mActor) {
      mActor->RevokeOwner(this);
      mActor->MaybeStartTeardown();
      mActor = nullptr;
    }

    OnShutdownThing();
  }

  // Allow extending classes to take action when shutdown.
  virtual void OnShutdownThing() {
    // by default do nothing
  }

 public:
  // Clear the weak references between the thing and its IPC actor.
  void RevokeActor(ActorType* aActor) {
    AssertIsValid();
    MOZ_DIAGNOSTIC_ASSERT(mActor);
    MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
    mActor->RevokeOwner(this);
    mActor = nullptr;

    // Also consider the ClientThing shutdown.  We simply set the flag
    // instead of calling ShutdownThing() to avoid calling MaybeStartTeardown()
    // on the destroyed actor.
    mShutdown = true;

    OnShutdownThing();
  }
};

}  // namespace mozilla::dom

#endif  // _mozilla_dom_ClientThing_h