tor-browser

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

AllocationPolicy.h (6355B)


      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
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef AllocationPolicy_h_
      8 #define AllocationPolicy_h_
      9 
     10 #include <queue>
     11 
     12 #include "MediaInfo.h"
     13 #include "PlatformDecoderModule.h"
     14 #include "TimeUnits.h"
     15 #include "mozilla/MozPromise.h"
     16 #include "mozilla/NotNull.h"
     17 #include "mozilla/ReentrantMonitor.h"
     18 #include "mozilla/StaticMutex.h"
     19 
     20 namespace mozilla {
     21 
     22 /**
     23 * Before calling PDMFactory::CreateDecoder(), Alloc() must be called on the
     24 * policy to get a token object as a permission to create a decoder. The
     25 * token should stay alive until Shutdown() is called on the decoder. The
     26 * destructor of the token will restore the decoder count so it is available
     27 * for next calls of Alloc().
     28 */
     29 class AllocPolicy {
     30  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AllocPolicy)
     31 
     32 public:
     33  class Token {
     34    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Token)
     35   protected:
     36    virtual ~Token() = default;
     37  };
     38  using Promise = MozPromise<RefPtr<Token>, bool, true>;
     39 
     40  // Acquire a token for decoder creation. Thread-safe.
     41  virtual RefPtr<Promise> Alloc() = 0;
     42 
     43 protected:
     44  virtual ~AllocPolicy() = default;
     45 };
     46 
     47 /**
     48 * This is a singleton which controls the number of decoders that can be created
     49 * concurrently.
     50 * Instance() will return the TrackType global AllocPolicy.
     51 * Instance() will always return a non-null value.
     52 */
     53 class GlobalAllocPolicy {
     54 public:
     55  // Get the singleton for the given track type. Thread-safe.
     56  static NotNull<AllocPolicy*> Instance(TrackInfo::TrackType aTrack);
     57 
     58 private:
     59  // Protect access to Instance().
     60  static StaticMutex sMutex MOZ_UNANNOTATED;
     61 };
     62 
     63 /** This the actual base implementation underneath all AllocPolicy objects and
     64 * control how many decoders can be created concurrently.
     65 * Alloc() must be called to get a token object as a permission to perform an
     66 * action. The token should stay alive until Shutdown() is called on the
     67 * decoder. The destructor of the token will restore the decoder count so it is
     68 * available for next calls of Alloc().
     69 **/
     70 class AllocPolicyImpl : public AllocPolicy {
     71 public:
     72  explicit AllocPolicyImpl(int aDecoderLimit);
     73  RefPtr<Promise> Alloc() override;
     74 
     75 protected:
     76  virtual ~AllocPolicyImpl();
     77  void RejectAll();
     78  int MaxDecoderLimit() const { return mMaxDecoderLimit; }
     79 
     80 private:
     81  class AutoDeallocToken;
     82  using PromisePrivate = Promise::Private;
     83  // Called by the destructor of TokenImpl to restore the decoder limit.
     84  void Dealloc();
     85  // Decrement the decoder limit and resolve a promise if available.
     86  void ResolvePromise(ReentrantMonitorAutoEnter& aProofOfLock);
     87 
     88  const int mMaxDecoderLimit;
     89  ReentrantMonitor mMonitor MOZ_UNANNOTATED;
     90  // The number of decoders available for creation.
     91  int mDecoderLimit;
     92  // Requests to acquire tokens.
     93  std::queue<RefPtr<PromisePrivate>> mPromises;
     94 };
     95 
     96 /**
     97 * This class allows to track and serialise a single decoder allocation at a
     98 * time
     99 */
    100 class SingleAllocPolicy : public AllocPolicyImpl {
    101  using TrackType = TrackInfo::TrackType;
    102 
    103 public:
    104  SingleAllocPolicy(TrackType aTrack, TaskQueue* aOwnerThread)
    105      : AllocPolicyImpl(1), mTrack(aTrack), mOwnerThread(aOwnerThread) {}
    106 
    107  RefPtr<Promise> Alloc() override;
    108 
    109  // Cancel the request to GlobalAllocPolicy and reject the current token
    110  // request. Note this must happen before mOwnerThread->BeginShutdown().
    111  void Cancel();
    112 
    113 private:
    114  class AutoDeallocCombinedToken;
    115  virtual ~SingleAllocPolicy();
    116 
    117  const TrackType mTrack;
    118  RefPtr<TaskQueue> mOwnerThread;
    119  MozPromiseHolder<Promise> mPendingPromise;
    120  MozPromiseRequestHolder<Promise> mTokenRequest;
    121 };
    122 
    123 class AllocationWrapper final : public MediaDataDecoder {
    124  using Token = AllocPolicy::Token;
    125 
    126 public:
    127  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AllocationWrapper, final);
    128 
    129  AllocationWrapper(already_AddRefed<MediaDataDecoder> aDecoder,
    130                    already_AddRefed<Token> aToken);
    131 
    132  RefPtr<InitPromise> Init() override { return mDecoder->Init(); }
    133  RefPtr<DecodePromise> Decode(MediaRawData* aSample) override {
    134    return mDecoder->Decode(aSample);
    135  }
    136  bool CanDecodeBatch() const override { return mDecoder->CanDecodeBatch(); }
    137  RefPtr<DecodePromise> DecodeBatch(
    138      nsTArray<RefPtr<MediaRawData>>&& aSamples) override {
    139    return mDecoder->DecodeBatch(std::move(aSamples));
    140  }
    141  RefPtr<DecodePromise> Drain() override { return mDecoder->Drain(); }
    142  RefPtr<FlushPromise> Flush() override { return mDecoder->Flush(); }
    143  bool IsHardwareAccelerated(nsACString& aFailureReason) const override {
    144    return mDecoder->IsHardwareAccelerated(aFailureReason);
    145  }
    146  nsCString GetDescriptionName() const override {
    147    return mDecoder->GetDescriptionName();
    148  }
    149  nsCString GetProcessName() const override {
    150    return mDecoder->GetProcessName();
    151  }
    152  nsCString GetCodecName() const override { return mDecoder->GetCodecName(); }
    153  void SetSeekThreshold(const media::TimeUnit& aTime) override {
    154    mDecoder->SetSeekThreshold(aTime);
    155  }
    156  bool SupportDecoderRecycling() const override {
    157    return mDecoder->SupportDecoderRecycling();
    158  }
    159  bool ShouldDecoderAlwaysBeRecycled() const override {
    160    return mDecoder->ShouldDecoderAlwaysBeRecycled();
    161  }
    162  RefPtr<ShutdownPromise> Shutdown() override;
    163  ConversionRequired NeedsConversion() const override {
    164    return mDecoder->NeedsConversion();
    165  }
    166 
    167  Maybe<PropertyValue> GetDecodeProperty(PropertyName aName) const override {
    168    return mDecoder->GetDecodeProperty(aName);
    169  }
    170 
    171  typedef MozPromise<RefPtr<MediaDataDecoder>, MediaResult,
    172                     /* IsExclusive = */ true>
    173      AllocateDecoderPromise;
    174  // Will create a decoder has soon as one can be created according to the
    175  // AllocPolicy (or GlobalAllocPolicy if aPolicy is null)
    176  // Warning: all aParams members must be valid until the promise has been
    177  // resolved, as some contains raw pointers to objects.
    178  static RefPtr<AllocateDecoderPromise> CreateDecoder(
    179      const CreateDecoderParams& aParams, AllocPolicy* aPolicy = nullptr);
    180 
    181 private:
    182  ~AllocationWrapper();
    183 
    184  RefPtr<MediaDataDecoder> mDecoder;
    185  RefPtr<Token> mToken;
    186 };
    187 
    188 }  // namespace mozilla
    189 
    190 #endif