DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (56e7b9127e89)

VCS Links

Line Code
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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * 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 _nsCacheRequest_h_
#define _nsCacheRequest_h_

#include "nspr.h"
#include "mozilla/CondVar.h"
#include "mozilla/Mutex.h"
#include "nsCOMPtr.h"
#include "nsICache.h"
#include "nsICacheListener.h"
#include "nsCacheSession.h"
#include "nsCacheService.h"


class nsCacheRequest : public PRCList
{
    typedef mozilla::CondVar CondVar;
    typedef mozilla::MutexAutoLock MutexAutoLock;
    typedef mozilla::Mutex Mutex;

private:
    friend class nsCacheService;
    friend class nsCacheEntry;
    friend class nsProcessRequestEvent;

    nsCacheRequest( const nsACString &    key,
                    nsICacheListener *    listener,
                    nsCacheAccessMode     accessRequested,
                    bool                  blockingMode,
                    nsCacheSession *      session)
        : mKey(key),
          mInfo(0),
          mListener(listener),
          mLock("nsCacheRequest.mLock"),
          mCondVar(mLock, "nsCacheRequest.mCondVar"),
          mProfileDir(session->ProfileDir())
    {
        MOZ_COUNT_CTOR(nsCacheRequest);
        PR_INIT_CLIST(this);
        SetAccessRequested(accessRequested);
        SetStoragePolicy(session->StoragePolicy());
        if (session->IsStreamBased())             MarkStreamBased();
        if (session->WillDoomEntriesIfExpired())  MarkDoomEntriesIfExpired();
        if (session->IsPrivate())                 MarkPrivate();
        if (blockingMode == nsICache::BLOCKING)    MarkBlockingMode();
        MarkWaitingForValidation();
        NS_IF_ADDREF(mListener);
    }

    ~nsCacheRequest()
    {
        MOZ_COUNT_DTOR(nsCacheRequest);
        NS_ASSERTION(PR_CLIST_IS_EMPTY(this), "request still on a list");

        if (mListener)
            nsCacheService::ReleaseObject_Locked(mListener, mEventTarget);
    }

    /**
     * Simple Accessors
     */
    enum CacheRequestInfo {
        eStoragePolicyMask         = 0x000000FF,
        eStreamBasedMask           = 0x00000100,
        ePrivateMask               = 0x00000200,
        eDoomEntriesIfExpiredMask  = 0x00001000,
        eBlockingModeMask          = 0x00010000,
        eWaitingForValidationMask  = 0x00100000,
        eAccessRequestedMask       = 0xFF000000
    };

    void SetAccessRequested(nsCacheAccessMode mode)
    {
        NS_ASSERTION(mode <= 0xFF, "too many bits in nsCacheAccessMode");
        mInfo &= ~eAccessRequestedMask;
        mInfo |= mode << 24;
    }

    nsCacheAccessMode AccessRequested()
    {
        return (nsCacheAccessMode)((mInfo >> 24) & 0xFF);
    }

    void MarkStreamBased()      { mInfo |=  eStreamBasedMask; }
    bool IsStreamBased()      { return (mInfo & eStreamBasedMask) != 0; }


    void   MarkDoomEntriesIfExpired()   { mInfo |=  eDoomEntriesIfExpiredMask; }
    bool WillDoomEntriesIfExpired()   { return (0 != (mInfo & eDoomEntriesIfExpiredMask)); }

    void   MarkBlockingMode()           { mInfo |= eBlockingModeMask; }
    bool IsBlocking()                 { return (0 != (mInfo & eBlockingModeMask)); }
    bool IsNonBlocking()              { return !(mInfo & eBlockingModeMask); }

    void SetStoragePolicy(nsCacheStoragePolicy policy)
    {
        NS_ASSERTION(policy <= 0xFF, "too many bits in nsCacheStoragePolicy");
        mInfo &= ~eStoragePolicyMask;  // clear storage policy bits
        mInfo |= policy;         // or in new bits
    }

    nsCacheStoragePolicy StoragePolicy()
    {
        return (nsCacheStoragePolicy)(mInfo & eStoragePolicyMask);
    }

    void   MarkPrivate() { mInfo |= ePrivateMask; }
    void   MarkPublic() { mInfo &= ~ePrivateMask; }
    bool   IsPrivate() { return (mInfo & ePrivateMask) != 0; }

    void   MarkWaitingForValidation() { mInfo |=  eWaitingForValidationMask; }
    void   DoneWaitingForValidation() { mInfo &= ~eWaitingForValidationMask; }
    bool WaitingForValidation()
    {
        return (mInfo & eWaitingForValidationMask) != 0;
    }

    nsresult
    WaitForValidation(void)
    {
        if (!WaitingForValidation()) {   // flag already cleared
            MarkWaitingForValidation();  // set up for next time
            return NS_OK;                // early exit;
        }
        {
            MutexAutoLock lock(mLock);
            while (WaitingForValidation()) {
                mCondVar.Wait();
            }
            MarkWaitingForValidation();  // set up for next time
        }
        return NS_OK;
    }

    void WakeUp(void) {
        DoneWaitingForValidation();
        MutexAutoLock lock(mLock);
        mCondVar.Notify();
    }

    /**
     * Data members
     */
    nsCString                  mKey;
    uint32_t                   mInfo;
    nsICacheListener *         mListener;  // strong ref
    nsCOMPtr<nsIEventTarget>   mEventTarget;
    Mutex                      mLock;
    CondVar                    mCondVar;
    nsCOMPtr<nsIFile>          mProfileDir;
};

#endif // _nsCacheRequest_h_