tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MediaSystemResourceManager.cpp (10650B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "MediaSystemResourceManager.h"
      8 
      9 #include "MediaSystemResourceClient.h"
     10 #include "MediaSystemResourceManagerChild.h"
     11 #include "mozilla/TaskQueue.h"
     12 #include "mozilla/layers/ImageBridgeChild.h"
     13 
     14 namespace mozilla {
     15 
     16 using namespace mozilla::ipc;
     17 using namespace mozilla::layers;
     18 
     19 /* static */
     20 StaticRefPtr<MediaSystemResourceManager> MediaSystemResourceManager::sSingleton;
     21 
     22 /* static */
     23 MediaSystemResourceManager* MediaSystemResourceManager::Get() {
     24  if (sSingleton) {
     25    return sSingleton;
     26  }
     27  MediaSystemResourceManager::Init();
     28  return sSingleton;
     29 }
     30 
     31 /* static */
     32 void MediaSystemResourceManager::Shutdown() {
     33  MOZ_ASSERT(InImageBridgeChildThread());
     34  if (sSingleton) {
     35    sSingleton->CloseIPC();
     36    sSingleton = nullptr;
     37  }
     38 }
     39 
     40 /* static */
     41 void MediaSystemResourceManager::Init() {
     42  RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
     43  if (!imageBridge) {
     44    NS_WARNING("ImageBridge does not exist");
     45    return;
     46  }
     47 
     48  if (InImageBridgeChildThread()) {
     49    if (!sSingleton) {
     50 #ifdef DEBUG
     51      static int timesCreated = 0;
     52      timesCreated++;
     53      MOZ_ASSERT(timesCreated == 1);
     54 #endif
     55      sSingleton = new MediaSystemResourceManager();
     56    }
     57    return;
     58  }
     59 
     60  ReentrantMonitor barrier MOZ_UNANNOTATED("MediaSystemResourceManager::Init");
     61  ReentrantMonitorAutoEnter mainThreadAutoMon(barrier);
     62  bool done = false;
     63 
     64  RefPtr<Runnable> runnable =
     65      NS_NewRunnableFunction("MediaSystemResourceManager::Init", [&]() {
     66        if (!sSingleton) {
     67          sSingleton = new MediaSystemResourceManager();
     68        }
     69        ReentrantMonitorAutoEnter childThreadAutoMon(barrier);
     70        done = true;
     71        barrier.NotifyAll();
     72      });
     73 
     74  imageBridge->GetThread()->Dispatch(runnable.forget());
     75 
     76  // should stop the thread until done.
     77  while (!done) {
     78    barrier.Wait();
     79  }
     80 }
     81 
     82 MediaSystemResourceManager::MediaSystemResourceManager()
     83    : mReentrantMonitor("MediaSystemResourceManager.mReentrantMonitor"),
     84      mShutDown(false),
     85      mChild(nullptr) {
     86  MOZ_ASSERT(InImageBridgeChildThread());
     87  OpenIPC();
     88 }
     89 
     90 MediaSystemResourceManager::~MediaSystemResourceManager() {
     91  MOZ_ASSERT(IsIpcClosed());
     92 }
     93 
     94 void MediaSystemResourceManager::OpenIPC() {
     95  MOZ_ASSERT(InImageBridgeChildThread());
     96  MOZ_ASSERT(!mChild);
     97 
     98  media::PMediaSystemResourceManagerChild* child =
     99      ImageBridgeChild::GetSingleton()
    100          ->SendPMediaSystemResourceManagerConstructor();
    101  mChild = static_cast<media::MediaSystemResourceManagerChild*>(child);
    102  mChild->SetManager(this);
    103 }
    104 
    105 void MediaSystemResourceManager::CloseIPC() {
    106  MOZ_ASSERT(InImageBridgeChildThread());
    107 
    108  if (!mChild) {
    109    return;
    110  }
    111  mChild->Destroy();
    112  mChild = nullptr;
    113  mShutDown = true;
    114 }
    115 
    116 void MediaSystemResourceManager::OnIpcClosed() { mChild = nullptr; }
    117 
    118 bool MediaSystemResourceManager::IsIpcClosed() { return mChild ? true : false; }
    119 
    120 void MediaSystemResourceManager::Register(MediaSystemResourceClient* aClient) {
    121  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    122  MOZ_ASSERT(aClient);
    123  MOZ_ASSERT(!mResourceClients.Contains(aClient->mId));
    124 
    125  mResourceClients.InsertOrUpdate(aClient->mId, aClient);
    126 }
    127 
    128 void MediaSystemResourceManager::Unregister(
    129    MediaSystemResourceClient* aClient) {
    130  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    131  MOZ_ASSERT(aClient);
    132  MOZ_ASSERT(mResourceClients.Contains(aClient->mId));
    133  MOZ_ASSERT(mResourceClients.Get(aClient->mId) == aClient);
    134 
    135  mResourceClients.Remove(aClient->mId);
    136 }
    137 
    138 bool MediaSystemResourceManager::SetListener(
    139    MediaSystemResourceClient* aClient,
    140    MediaSystemResourceReservationListener* aListener) {
    141  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    142  MOZ_ASSERT(aClient);
    143 
    144  MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
    145  MOZ_ASSERT(client);
    146 
    147  if (!client) {
    148    return false;
    149  }
    150  // State Check
    151  if (aClient->mResourceState !=
    152      MediaSystemResourceClient::RESOURCE_STATE_START) {
    153    return false;
    154  }
    155  aClient->mListener = aListener;
    156  return true;
    157 }
    158 
    159 void MediaSystemResourceManager::Acquire(MediaSystemResourceClient* aClient) {
    160  MOZ_ASSERT(aClient);
    161  MOZ_ASSERT(!InImageBridgeChildThread());
    162 
    163  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    164  MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
    165  MOZ_ASSERT(client);
    166  MOZ_ASSERT(client == aClient);
    167 
    168  aClient->mIsSync = false;  // async request
    169 
    170  if (!client) {
    171    HandleAcquireResult(aClient->mId, false);
    172    return;
    173  }
    174  // State Check
    175  if (aClient->mResourceState !=
    176      MediaSystemResourceClient::RESOURCE_STATE_START) {
    177    HandleAcquireResult(aClient->mId, false);
    178    return;
    179  }
    180  aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING;
    181  ImageBridgeChild::GetSingleton()->GetThread()->Dispatch(
    182      NewRunnableMethod<uint32_t>("MediaSystemResourceManager::DoAcquire", this,
    183                                  &MediaSystemResourceManager::DoAcquire,
    184                                  aClient->mId));
    185 }
    186 
    187 bool MediaSystemResourceManager::AcquireSyncNoWait(
    188    MediaSystemResourceClient* aClient) {
    189  MOZ_ASSERT(aClient);
    190  MOZ_ASSERT(!InImageBridgeChildThread());
    191 
    192  ReentrantMonitor barrier MOZ_UNANNOTATED(
    193      "MediaSystemResourceManager::AcquireSyncNoWait");
    194  ReentrantMonitorAutoEnter autoMon(barrier);
    195  bool done = false;
    196  {
    197    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    198    MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
    199    MOZ_ASSERT(client);
    200    MOZ_ASSERT(client == aClient);
    201 
    202    aClient->mIsSync = true;  // sync request
    203 
    204    if (InImageBridgeChildThread()) {
    205      HandleAcquireResult(aClient->mId, false);
    206      return false;
    207    }
    208    if (!client || client != aClient) {
    209      HandleAcquireResult(aClient->mId, false);
    210      return false;
    211    }
    212    // State Check
    213    if (aClient->mResourceState !=
    214        MediaSystemResourceClient::RESOURCE_STATE_START) {
    215      HandleAcquireResult(aClient->mId, false);
    216      return false;
    217    }
    218    // Hold barrier Monitor until acquire task end.
    219    aClient->mAcquireSyncWaitMonitor = &barrier;
    220    aClient->mAcquireSyncWaitDone = &done;
    221    aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING;
    222  }
    223 
    224  ImageBridgeChild::GetSingleton()->GetThread()->Dispatch(
    225      NewRunnableMethod<uint32_t>("MediaSystemResourceManager::DoAcquire", this,
    226                                  &MediaSystemResourceManager::DoAcquire,
    227                                  aClient->mId));
    228 
    229  // should stop the thread until done.
    230  while (!done) {
    231    barrier.Wait();
    232  }
    233 
    234  {
    235    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    236    if (aClient->mResourceState !=
    237        MediaSystemResourceClient::RESOURCE_STATE_ACQUIRED) {
    238      return false;
    239    }
    240    return true;
    241  }
    242 }
    243 
    244 void MediaSystemResourceManager::DoAcquire(uint32_t aId) {
    245  MOZ_ASSERT(InImageBridgeChildThread());
    246  if (mShutDown || !mChild) {
    247    HandleAcquireResult(aId, false);
    248    return;
    249  }
    250  {
    251    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    252    MediaSystemResourceClient* client = mResourceClients.Get(aId);
    253    MOZ_ASSERT(client);
    254 
    255    if (!client || client->mResourceState !=
    256                       MediaSystemResourceClient::RESOURCE_STATE_WAITING) {
    257      HandleAcquireResult(aId, false);
    258      return;
    259    }
    260    MOZ_ASSERT(aId == client->mId);
    261    bool willWait = !client->mAcquireSyncWaitMonitor ? true : false;
    262    mChild->SendAcquire(client->mId, client->mResourceType, willWait);
    263  }
    264 }
    265 
    266 void MediaSystemResourceManager::ReleaseResource(
    267    MediaSystemResourceClient* aClient) {
    268  MOZ_ASSERT(aClient);
    269  {
    270    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    271    MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
    272    MOZ_ASSERT(client);
    273    MOZ_ASSERT(client == aClient);
    274 
    275    if (!client || client != aClient ||
    276        aClient->mResourceState ==
    277            MediaSystemResourceClient::RESOURCE_STATE_START ||
    278        aClient->mResourceState ==
    279            MediaSystemResourceClient::RESOURCE_STATE_END) {
    280      aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END;
    281      return;
    282    }
    283 
    284    aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END;
    285 
    286    ImageBridgeChild::GetSingleton()->GetThread()->Dispatch(
    287        NewRunnableMethod<uint32_t>(
    288            "MediaSystemResourceManager::DoRelease", this,
    289            &MediaSystemResourceManager::DoRelease, aClient->mId));
    290  }
    291 }
    292 
    293 void MediaSystemResourceManager::DoRelease(uint32_t aId) {
    294  MOZ_ASSERT(InImageBridgeChildThread());
    295  if (mShutDown || !mChild) {
    296    return;
    297  }
    298  mChild->SendRelease(aId);
    299 }
    300 
    301 void MediaSystemResourceManager::RecvResponse(uint32_t aId, bool aSuccess) {
    302  HandleAcquireResult(aId, aSuccess);
    303 }
    304 
    305 void MediaSystemResourceManager::HandleAcquireResult(uint32_t aId,
    306                                                     bool aSuccess) {
    307  if (!InImageBridgeChildThread()) {
    308    ImageBridgeChild::GetSingleton()->GetThread()->Dispatch(
    309        NewRunnableMethod<uint32_t, bool>(
    310            "MediaSystemResourceManager::HandleAcquireResult", this,
    311            &MediaSystemResourceManager::HandleAcquireResult, aId, aSuccess));
    312    return;
    313  }
    314 
    315  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    316  MediaSystemResourceClient* client = mResourceClients.Get(aId);
    317  if (!client) {
    318    // Client was already unregistered.
    319    return;
    320  }
    321  if (client->mResourceState !=
    322      MediaSystemResourceClient::RESOURCE_STATE_WAITING) {
    323    return;
    324  }
    325 
    326  // Update state
    327  if (aSuccess) {
    328    client->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_ACQUIRED;
    329  } else {
    330    client->mResourceState =
    331        MediaSystemResourceClient::RESOURCE_STATE_NOT_ACQUIRED;
    332  }
    333 
    334  if (client->mIsSync) {
    335    if (client->mAcquireSyncWaitMonitor) {
    336      // Notify AcquireSync() complete
    337      MOZ_ASSERT(client->mAcquireSyncWaitDone);
    338      ReentrantMonitorAutoEnter autoMon(*client->mAcquireSyncWaitMonitor);
    339      *client->mAcquireSyncWaitDone = true;
    340      client->mAcquireSyncWaitMonitor->NotifyAll();
    341      client->mAcquireSyncWaitMonitor = nullptr;
    342      client->mAcquireSyncWaitDone = nullptr;
    343    }
    344  } else {
    345    // Notify Acquire() result
    346    if (client->mListener) {
    347      if (aSuccess) {
    348        client->mListener->ResourceReserved();
    349      } else {
    350        client->mListener->ResourceReserveFailed();
    351      }
    352    }
    353  }
    354 }
    355 
    356 }  // namespace mozilla