Changeset 219298 in webkit


Ignore:
Timestamp:
Jul 10, 2017 10:43:38 AM (7 years ago)
Author:
beidson@apple.com
Message:

Cleanup lifetime issues of UniqueIDBDatabase and IDBBackingStore.
<rdar://problem/32908525> and https://bugs.webkit.org/show_bug.cgi?id=174244

Reviewed by David Kilzer and Alex Christensen.

Source/WebCore:

No targeted test possible, implicitly covered by all IDB tests.

The original idea behind UniqueIDBDatabase lifetime was that they are ThreadSafeRefCounted and
we take protector Refs when any operation that needs it alive is in flight.

This added variability to their lifetime which made it difficult to enforce a few different
design invariants, namely:

  • UniqueIBDDatabase objects are always created and destroyed only on the main thread.
  • IDBBackingStore objects are always created and destroyed only on the database thread.

This patch removes the ref counting and instead ties UniqueIDBDatabase lifetime to a
std::unique_ptr that is owned by the IDBServer.

Whenever any operations on the UniqueIDBDatabase are in flight it is kept alive by virtue
of that unique_ptr in the IDBServer. Once a UniqueIDBDatabase is completely done with all of
its work, the following happens:

  • On the main thread the IDBServer removes the unique_ptr owning the UniqueIDBDatabase from its map.
  • It hands the unique_ptr to the UniqueIDBDatabase itself, which schedules one final database thread task.
  • That database thread task is to destroy the IDBBackingStore, kill its message queues, and then message back to the main thread for one final task.
  • That main thread task is to release the unique_ptr, resulting in destruction of the UniqueIDBDatabase object.

This is safe, predictable, solves the lifetime issues that r218516 originally tried to solve,
and solves the lifetime issues that r218516 introduced.

(This patch also adds many more assertions to cover various design invariants throughout the
lifecycle of a particular UniqueIDBDatabase)

ASSERT that IDBBackingStores are only ever created and destroyed on the background thread:

  • Modules/indexeddb/server/IDBBackingStore.h:

(WebCore::IDBServer::IDBBackingStore::~IDBBackingStore):
(WebCore::IDBServer::IDBBackingStore::IDBBackingStore):

Transition UniqueIDBDatabase ownership from a RefPtr to a std::unique_ptr:

  • Modules/indexeddb/server/IDBServer.cpp:

(WebCore::IDBServer::IDBServer::getOrCreateUniqueIDBDatabase):
(WebCore::IDBServer::IDBServer::closeAndTakeUniqueIDBDatabase):
(WebCore::IDBServer::IDBServer::closeAndDeleteDatabasesModifiedSince):
(WebCore::IDBServer::IDBServer::closeAndDeleteDatabasesForOrigins):
(WebCore::IDBServer::IDBServer::closeUniqueIDBDatabase): Deleted.

  • Modules/indexeddb/server/IDBServer.h:

Make all the other changes mentioned above:

  • Modules/indexeddb/server/UniqueIDBDatabase.cpp:

(WebCore::IDBServer::UniqueIDBDatabase::~UniqueIDBDatabase): Bulk up on ASSERTs
(WebCore::IDBServer::UniqueIDBDatabase::openDatabaseConnection):
(WebCore::IDBServer::UniqueIDBDatabase::performUnconditionalDeleteBackingStore):
(WebCore::IDBServer::UniqueIDBDatabase::scheduleShutdownForClose):
(WebCore::IDBServer::UniqueIDBDatabase::shutdownForClose):
(WebCore::IDBServer::UniqueIDBDatabase::didShutdownForClose):
(WebCore::IDBServer::UniqueIDBDatabase::didDeleteBackingStore):
(WebCore::IDBServer::UniqueIDBDatabase::handleCurrentOperation):
(WebCore::IDBServer::UniqueIDBDatabase::performIterateCursor):
(WebCore::IDBServer::UniqueIDBDatabase::performPrefetchCursor):
(WebCore::IDBServer::UniqueIDBDatabase::operationAndTransactionTimerFired):
(WebCore::IDBServer::UniqueIDBDatabase::activateTransactionInBackingStore):
(WebCore::IDBServer::UniqueIDBDatabase::transactionCompleted):
(WebCore::IDBServer::UniqueIDBDatabase::postDatabaseTask):
(WebCore::IDBServer::UniqueIDBDatabase::postDatabaseTaskReply):
(WebCore::IDBServer::UniqueIDBDatabase::executeNextDatabaseTask):
(WebCore::IDBServer::UniqueIDBDatabase::executeNextDatabaseTaskReply):
(WebCore::IDBServer::UniqueIDBDatabase::maybeFinishHardClose):
(WebCore::IDBServer::UniqueIDBDatabase::isDoneWithHardClose):
(WebCore::IDBServer::UniqueIDBDatabase::immediateCloseForUserDelete):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformUnconditionalDeleteBackingStore): Deleted.

  • Modules/indexeddb/server/UniqueIDBDatabase.h:

(WebCore::IDBServer::UniqueIDBDatabase::create): Deleted.

Source/WTF:

Add proper "kill" support to CrossThreadQueue, as well as isEmpty() support.

  • wtf/CrossThreadQueue.h:

(WTF::CrossThreadQueue<DataType>::append):
(WTF::CrossThreadQueue<DataType>::kill):
(WTF::CrossThreadQueue<DataType>::isKilled):
(WTF::CrossThreadQueue<DataType>::isEmpty):
(WTF::CrossThreadQueue::isKilled): Deleted.

Location:
trunk/Source
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r219281 r219298  
     12017-07-10  Brady Eidson  <beidson@apple.com>
     2
     3        Cleanup lifetime issues of UniqueIDBDatabase and IDBBackingStore.
     4        <rdar://problem/32908525> and https://bugs.webkit.org/show_bug.cgi?id=174244
     5
     6        Reviewed by David Kilzer and Alex Christensen.
     7
     8        Add proper "kill" support to CrossThreadQueue, as well as isEmpty() support.
     9
     10        * wtf/CrossThreadQueue.h:
     11        (WTF::CrossThreadQueue<DataType>::append):
     12        (WTF::CrossThreadQueue<DataType>::kill):
     13        (WTF::CrossThreadQueue<DataType>::isKilled):
     14        (WTF::CrossThreadQueue<DataType>::isEmpty):
     15        (WTF::CrossThreadQueue::isKilled): Deleted.
     16
    1172017-07-09  Yusuke Suzuki  <utatane.tea@gmail.com>
    218
  • trunk/Source/WTF/wtf/CrossThreadQueue.h

    r218594 r219298  
    4747    std::optional<DataType> tryGetMessage();
    4848
    49     bool isKilled() const { return false; }
     49    void kill();
     50    bool isKilled() const;
     51    bool isEmpty() const;
    5052
    5153private:
     
    5355    Condition m_condition;
    5456    Deque<DataType> m_queue;
     57    bool m_killed { false };
    5558};
    5659
     
    5962{
    6063    LockHolder lock(m_lock);
     64    ASSERT(!m_killed);
    6165    m_queue.append(WTFMove(message));
    6266    m_condition.notifyOne();
     
    9195}
    9296
     97template<typename DataType>
     98void CrossThreadQueue<DataType>::kill()
     99{
     100    LockHolder lock(m_lock);
     101    m_killed = true;
     102    m_condition.notifyAll();
     103}
     104
     105template<typename DataType>
     106bool CrossThreadQueue<DataType>::isKilled() const
     107{
     108    LockHolder lock(m_lock);
     109    return m_killed;
     110}
     111
     112template<typename DataType>
     113bool CrossThreadQueue<DataType>::isEmpty() const
     114{
     115    LockHolder lock(m_lock);
     116    return m_queue.isEmpty();
     117}
     118
    93119} // namespace WTF
    94120
  • trunk/Source/WebCore/ChangeLog

    r219297 r219298  
     12017-07-10  Brady Eidson  <beidson@apple.com>
     2
     3        Cleanup lifetime issues of UniqueIDBDatabase and IDBBackingStore.
     4        <rdar://problem/32908525> and https://bugs.webkit.org/show_bug.cgi?id=174244
     5
     6        Reviewed by David Kilzer and Alex Christensen.
     7
     8        No targeted test possible, implicitly covered by all IDB tests.
     9
     10        The original idea behind UniqueIDBDatabase lifetime was that they are ThreadSafeRefCounted and
     11        we take protector Refs when any operation that needs it alive is in flight.
     12       
     13        This added variability to their lifetime which made it difficult to enforce a few different
     14        design invariants, namely:
     15            - UniqueIBDDatabase objects are always created and destroyed only on the main thread.
     16            - IDBBackingStore objects are always created and destroyed only on the database thread.
     17       
     18        This patch removes the ref counting and instead ties UniqueIDBDatabase lifetime to a
     19        std::unique_ptr that is owned by the IDBServer.
     20       
     21        Whenever any operations on the UniqueIDBDatabase are in flight it is kept alive by virtue
     22        of that unique_ptr in the IDBServer. Once a UniqueIDBDatabase is completely done with all of
     23        its work, the following happens:
     24            - On the main thread the IDBServer removes the unique_ptr owning the UniqueIDBDatabase
     25              from its map.
     26            - It hands the unique_ptr to the UniqueIDBDatabase itself, which schedules one final
     27              database thread task.
     28            - That database thread task is to destroy the IDBBackingStore, kill its message queues,
     29              and then message back to the main thread for one final task.
     30            - That main thread task is to release the unique_ptr, resulting in destruction of the
     31              UniqueIDBDatabase object.
     32       
     33        This is safe, predictable, solves the lifetime issues that r218516 originally tried to solve,
     34        and solves the lifetime issues that r218516 introduced.
     35
     36        (This patch also adds many more assertions to cover various design invariants throughout the
     37        lifecycle of a particular UniqueIDBDatabase)
     38
     39        ASSERT that IDBBackingStores are only ever created and destroyed on the background thread:
     40        * Modules/indexeddb/server/IDBBackingStore.h:
     41        (WebCore::IDBServer::IDBBackingStore::~IDBBackingStore):
     42        (WebCore::IDBServer::IDBBackingStore::IDBBackingStore):
     43       
     44        Transition UniqueIDBDatabase ownership from a RefPtr to a std::unique_ptr:
     45        * Modules/indexeddb/server/IDBServer.cpp:
     46        (WebCore::IDBServer::IDBServer::getOrCreateUniqueIDBDatabase):
     47        (WebCore::IDBServer::IDBServer::closeAndTakeUniqueIDBDatabase):
     48        (WebCore::IDBServer::IDBServer::closeAndDeleteDatabasesModifiedSince):
     49        (WebCore::IDBServer::IDBServer::closeAndDeleteDatabasesForOrigins):
     50        (WebCore::IDBServer::IDBServer::closeUniqueIDBDatabase): Deleted.
     51        * Modules/indexeddb/server/IDBServer.h:
     52       
     53        Make all the other changes mentioned above:
     54        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
     55        (WebCore::IDBServer::UniqueIDBDatabase::~UniqueIDBDatabase): Bulk up on ASSERTs
     56        (WebCore::IDBServer::UniqueIDBDatabase::openDatabaseConnection):
     57        (WebCore::IDBServer::UniqueIDBDatabase::performUnconditionalDeleteBackingStore):
     58        (WebCore::IDBServer::UniqueIDBDatabase::scheduleShutdownForClose):
     59        (WebCore::IDBServer::UniqueIDBDatabase::shutdownForClose):
     60        (WebCore::IDBServer::UniqueIDBDatabase::didShutdownForClose):
     61        (WebCore::IDBServer::UniqueIDBDatabase::didDeleteBackingStore):
     62        (WebCore::IDBServer::UniqueIDBDatabase::handleCurrentOperation):
     63        (WebCore::IDBServer::UniqueIDBDatabase::performIterateCursor):
     64        (WebCore::IDBServer::UniqueIDBDatabase::performPrefetchCursor):
     65        (WebCore::IDBServer::UniqueIDBDatabase::operationAndTransactionTimerFired):
     66        (WebCore::IDBServer::UniqueIDBDatabase::activateTransactionInBackingStore):
     67        (WebCore::IDBServer::UniqueIDBDatabase::transactionCompleted):
     68        (WebCore::IDBServer::UniqueIDBDatabase::postDatabaseTask):
     69        (WebCore::IDBServer::UniqueIDBDatabase::postDatabaseTaskReply):
     70        (WebCore::IDBServer::UniqueIDBDatabase::executeNextDatabaseTask):
     71        (WebCore::IDBServer::UniqueIDBDatabase::executeNextDatabaseTaskReply):
     72        (WebCore::IDBServer::UniqueIDBDatabase::maybeFinishHardClose):
     73        (WebCore::IDBServer::UniqueIDBDatabase::isDoneWithHardClose):
     74        (WebCore::IDBServer::UniqueIDBDatabase::immediateCloseForUserDelete):
     75        (WebCore::IDBServer::UniqueIDBDatabase::didPerformUnconditionalDeleteBackingStore): Deleted.
     76        * Modules/indexeddb/server/UniqueIDBDatabase.h:
     77        (WebCore::IDBServer::UniqueIDBDatabase::create): Deleted.
     78
    1792017-07-10  Chris Dumez  <cdumez@apple.com>
    280
  • trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h

    r209977 r219298  
    3030#include "IDBDatabaseInfo.h"
    3131#include "IDBError.h"
     32#include <wtf/MainThread.h>
    3233
    3334namespace WebCore {
     
    6566class IDBBackingStore {
    6667public:
    67     virtual ~IDBBackingStore() { }
     68    virtual ~IDBBackingStore() { RELEASE_ASSERT(!isMainThread()); }
    6869
    6970    virtual IDBError getOrEstablishDatabaseInfo(IDBDatabaseInfo&) = 0;
     
    99100    virtual bool supportsSimultaneousTransactions() = 0;
    100101    virtual bool isEphemeral() = 0;
     102
     103protected:
     104    IDBBackingStore() { RELEASE_ASSERT(!isMainThread()); }
    101105};
    102106
  • trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp

    r218816 r219298  
    122122    auto uniqueIDBDatabase = m_uniqueIDBDatabaseMap.add(identifier, nullptr);
    123123    if (uniqueIDBDatabase.isNewEntry)
    124         uniqueIDBDatabase.iterator->value = UniqueIDBDatabase::create(*this, identifier);
     124        uniqueIDBDatabase.iterator->value = std::make_unique<UniqueIDBDatabase>(*this, identifier);
    125125
    126126    return *uniqueIDBDatabase.iterator->value;
     
    172172}
    173173
    174 void IDBServer::closeUniqueIDBDatabase(UniqueIDBDatabase& database)
     174std::unique_ptr<UniqueIDBDatabase> IDBServer::closeAndTakeUniqueIDBDatabase(UniqueIDBDatabase& database)
    175175{
    176176    LOG(IndexedDB, "IDBServer::closeUniqueIDBDatabase");
    177177    ASSERT(isMainThread());
    178178
    179     m_uniqueIDBDatabaseMap.remove(database.identifier());
     179    auto uniquePointer = m_uniqueIDBDatabaseMap.take(database.identifier());
     180    ASSERT(uniquePointer);
     181
     182    return uniquePointer;
    180183}
    181184
     
    546549    }
    547550
    548     HashSet<RefPtr<UniqueIDBDatabase>> openDatabases;
     551    HashSet<UniqueIDBDatabase*> openDatabases;
    549552    for (auto* connection : m_databaseConnections.values())
    550553        openDatabases.add(&connection->database());
     
    562565    ASSERT_UNUSED(addResult, addResult.isNewEntry);
    563566
    564     HashSet<RefPtr<UniqueIDBDatabase>> openDatabases;
     567    HashSet<UniqueIDBDatabase*> openDatabases;
    565568    for (auto* connection : m_databaseConnections.values()) {
    566569        const auto& identifier = connection->database().identifier();
  • trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h

    r218816 r219298  
    9999    void unregisterTransaction(UniqueIDBDatabaseTransaction&);
    100100
    101     void closeUniqueIDBDatabase(UniqueIDBDatabase&);
     101    std::unique_ptr<UniqueIDBDatabase> closeAndTakeUniqueIDBDatabase(UniqueIDBDatabase&);
    102102
    103103    std::unique_ptr<IDBBackingStore> createBackingStore(const IDBDatabaseIdentifier&);
     
    123123
    124124    HashMap<uint64_t, RefPtr<IDBConnectionToClient>> m_connectionMap;
    125     HashMap<IDBDatabaseIdentifier, RefPtr<UniqueIDBDatabase>> m_uniqueIDBDatabaseMap;
     125    HashMap<IDBDatabaseIdentifier, std::unique_ptr<UniqueIDBDatabase>> m_uniqueIDBDatabaseMap;
    126126
    127127    RefPtr<Thread> m_thread { nullptr };
  • trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp

    r219204 r219298  
    7474    ASSERT(m_clientClosePendingDatabaseConnections.isEmpty());
    7575    ASSERT(m_serverClosePendingDatabaseConnections.isEmpty());
    76     ASSERT(!m_queuedTaskCount);
     76
     77    RELEASE_ASSERT(m_databaseQueue.isKilled());
     78    RELEASE_ASSERT(m_databaseReplyQueue.isKilled());
     79    RELEASE_ASSERT(!m_backingStore);
    7780}
    7881
     
    8790    LOG(IndexedDB, "UniqueIDBDatabase::openDatabaseConnection");
    8891    ASSERT(!m_hardClosedForUserDelete);
     92    ASSERT(isMainThread());
    8993
    9094    m_pendingOpenDBRequests.add(ServerOpenDBRequest::create(connection, requestData));
     
    261265    LOG(IndexedDB, "(db) UniqueIDBDatabase::performUnconditionalDeleteBackingStore");
    262266
    263     if (!m_backingStore)
    264         return;
    265 
    266     m_backingStore->deleteBackingStore();
     267    if (m_backingStore)
     268        m_backingStore->deleteBackingStore();
     269
     270    shutdownForClose();
     271}
     272
     273void UniqueIDBDatabase::scheduleShutdownForClose()
     274{
     275    ASSERT(isMainThread());
     276
     277    m_owningPointerForClose = m_server.closeAndTakeUniqueIDBDatabase(*this);
     278    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::shutdownForClose));
     279}
     280
     281void UniqueIDBDatabase::shutdownForClose()
     282{
     283    ASSERT(!isMainThread());
     284    ASSERT(m_owningPointerForClose.get() == this);
     285
     286    LOG(IndexedDB, "(db) UniqueIDBDatabase::shutdownForClose");
     287
    267288    m_backingStore = nullptr;
    268289    m_backingStoreSupportsSimultaneousTransactions = false;
    269290    m_backingStoreIsEphemeral = false;
     291
     292    ASSERT(m_databaseQueue.isEmpty());
     293    m_databaseQueue.kill();
     294
     295    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didShutdownForClose));
     296}
     297
     298void UniqueIDBDatabase::didShutdownForClose()
     299{
     300    ASSERT(m_databaseReplyQueue.isEmpty());
     301    m_databaseReplyQueue.kill();
    270302}
    271303
     
    279311    ASSERT(m_pendingTransactions.isEmpty());
    280312    ASSERT(m_openDatabaseConnections.isEmpty());
     313    ASSERT(!m_backingStore);
    281314
    282315    // It's possible that the openDBRequest was cancelled from client-side after the delete was already dispatched to the backingstore.
     
    301334
    302335    if (m_clientClosePendingDatabaseConnections.isEmpty() && m_pendingOpenDBRequests.isEmpty()) {
    303         m_server.closeUniqueIDBDatabase(*this);
     336        // This UniqueIDBDatabase is now ready to be deleted.
     337        ASSERT(m_databaseQueue.isEmpty());
     338        ASSERT(m_databaseReplyQueue.isEmpty());
     339        m_databaseQueue.kill();
     340        m_databaseReplyQueue.kill();
     341        callOnMainThread([owningRef = m_server.closeAndTakeUniqueIDBDatabase(*this)]{ });
    304342        return;
    305343    }
    306344
    307345    invokeOperationAndTransactionTimer();
    308 }
    309 
    310 void UniqueIDBDatabase::didPerformUnconditionalDeleteBackingStore()
    311 {
    312     // This function is a placeholder so the database thread can message back to the main thread.
    313     ASSERT(m_hardClosedForUserDelete);
    314346}
    315347
     
    349381    ASSERT(!m_hardClosedForUserDelete);
    350382    ASSERT(m_currentOpenDBRequest);
    351 
    352     RefPtr<UniqueIDBDatabase> protectedThis(this);
    353383
    354384    if (m_currentOpenDBRequest->isOpenRequest())
     
    12361266
    12371267    if (error.isNull()) {
    1238         auto addResult = m_prefetchProtectors.add(cursorIdentifier, nullptr);
    1239         if (addResult.isNewEntry) {
    1240             addResult.iterator->value = this;
     1268        auto addResult = m_cursorPrefetches.add(cursorIdentifier);
     1269        if (addResult.isNewEntry)
    12411270            postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPrefetchCursor, transactionIdentifier, cursorIdentifier));
    1242         }
    12431271    }
    12441272
     
    12491277{
    12501278    ASSERT(!isMainThread());
    1251     ASSERT(m_prefetchProtectors.contains(cursorIdentifier));
     1279    ASSERT(m_cursorPrefetches.contains(cursorIdentifier));
    12521280    LOG(IndexedDB, "(db) UniqueIDBDatabase::performPrefetchCursor");
    12531281
     
    12551283        postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPrefetchCursor, transactionIdentifier, cursorIdentifier));
    12561284    else
    1257         postDatabaseTaskReply(WTF::Function<void ()>([prefetchProtector = m_prefetchProtectors.take(cursorIdentifier)]() { }));
     1285        m_cursorPrefetches.remove(cursorIdentifier);
    12581286}
    12591287
     
    15241552    LOG(IndexedDB, "(main) UniqueIDBDatabase::operationAndTransactionTimerFired");
    15251553    ASSERT(!m_hardClosedForUserDelete);
    1526 
    1527     RefPtr<UniqueIDBDatabase> protectedThis(this);
     1554    ASSERT(isMainThread());
    15281555
    15291556    // This UniqueIDBDatabase might be no longer in use by any web page.
     
    15321559        ASSERT(m_pendingTransactions.isEmpty());
    15331560        ASSERT(!hasUnfinishedTransactions());
    1534         m_server.closeUniqueIDBDatabase(*this);
     1561
     1562        scheduleShutdownForClose();
    15351563        return;
    15361564    }
     
    15681596{
    15691597    LOG(IndexedDB, "(main) UniqueIDBDatabase::activateTransactionInBackingStore");
    1570 
    1571     RefPtr<UniqueIDBDatabase> protectedThis(this);
     1598    ASSERT(isMainThread());
     1599
    15721600    RefPtr<UniqueIDBDatabaseTransaction> refTransaction(&transaction);
    15731601
    1574     ErrorCallback callback = [protectedThis, refTransaction](const IDBError& error) {
     1602    ErrorCallback callback = [refTransaction](const IDBError& error) {
    15751603        refTransaction->didActivateInBackingStore(error);
    15761604    };
     
    16771705    ASSERT(!m_inProgressTransactions.contains(transaction->info().identifier()));
    16781706    ASSERT(!m_finishingTransactions.contains(transaction->info().identifier()));
     1707    ASSERT(isMainThread());
    16791708
    16801709    for (auto objectStore : transaction->objectStoreIdentifiers()) {
     
    16951724    // If this transaction completing was the last of those operations, we can finally delete this UniqueIDBDatabase.
    16961725    if (m_clientClosePendingDatabaseConnections.isEmpty() && m_pendingOpenDBRequests.isEmpty() && !m_databaseInfo) {
    1697         m_server.closeUniqueIDBDatabase(*this);
     1726        scheduleShutdownForClose();
    16981727        return;
    16991728    }
     
    17081737void UniqueIDBDatabase::postDatabaseTask(CrossThreadTask&& task)
    17091738{
    1710     m_databaseQueue.append([protectedThis = makeRef(*this), task = WTFMove(task)]() mutable {
    1711         task.performTask();
    1712     });
    1713     ++m_queuedTaskCount;
    1714 
     1739    m_databaseQueue.append(WTFMove(task));
    17151740    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::executeNextDatabaseTask));
    17161741}
     
    17201745    ASSERT(!isMainThread());
    17211746
    1722     m_databaseReplyQueue.append([protectedThis = makeRef(*this), task = WTFMove(task)]() mutable {
    1723         task.performTask();
    1724     });
    1725     ++m_queuedTaskCount;
    1726 
     1747    m_databaseReplyQueue.append(WTFMove(task));
    17271748    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::executeNextDatabaseTaskReply));
    17281749}
     
    17311752{
    17321753    ASSERT(!isMainThread());
    1733     ASSERT(m_queuedTaskCount);
     1754    ASSERT(!m_databaseQueue.isKilled());
    17341755
    17351756    auto task = m_databaseQueue.tryGetMessage();
    17361757    ASSERT(task);
    17371758
    1738     (*task)();
    1739     --m_queuedTaskCount;
    1740 
    1741     // Release the task on the main thread in case it holds the last reference to this,
    1742     // as UniqueIDBDatabase objects must be deleted on the main thread.
    1743     callOnMainThread([task = WTFMove(task)] {
    1744     });
     1759    task->performTask();
    17451760}
    17461761
     
    17481763{
    17491764    ASSERT(isMainThread());
    1750     ASSERT(m_queuedTaskCount);
     1765    ASSERT(!m_databaseReplyQueue.isKilled());
    17511766
    17521767    auto task = m_databaseReplyQueue.tryGetMessage();
    17531768    ASSERT(task);
    17541769
    1755     (*task)();
    1756     --m_queuedTaskCount;
     1770    task->performTask();
    17571771
    17581772    // If this database was force closed (e.g. for a user delete) and there are no more
     
    17631777void UniqueIDBDatabase::maybeFinishHardClose()
    17641778{
    1765     if (m_hardCloseProtector && isDoneWithHardClose()) {
     1779    if (m_owningPointerForClose && isDoneWithHardClose()) {
    17661780        callOnMainThread([this] {
    17671781            ASSERT(isDoneWithHardClose());
    1768             m_hardCloseProtector = nullptr;
     1782            m_owningPointerForClose = nullptr;
    17691783        });
    17701784    }
     
    17731787bool UniqueIDBDatabase::isDoneWithHardClose()
    17741788{
    1775     return !m_queuedTaskCount && m_clientClosePendingDatabaseConnections.isEmpty() && m_serverClosePendingDatabaseConnections.isEmpty();
     1789    return m_databaseQueue.isKilled() && m_clientClosePendingDatabaseConnections.isEmpty() && m_serverClosePendingDatabaseConnections.isEmpty();
    17761790}
    17771791
     
    17891803    LOG(IndexedDB, "UniqueIDBDatabase::immediateCloseForUserDelete - Cancelling (%i, %i, %i, %i) callbacks", m_errorCallbacks.size(), m_keyDataCallbacks.size(), m_getResultCallbacks.size(), m_countCallbacks.size());
    17901804
     1805    ASSERT(isMainThread());
     1806
    17911807    // Error out all transactions
    17921808    Vector<IDBResourceIdentifier> inProgressIdentifiers;
     
    18481864    // database connections confirm that they have closed.
    18491865    m_hardClosedForUserDelete = true;
    1850     m_hardCloseProtector = this;
     1866
     1867    // Remove this UniqueIDBDatabase from the IDBServer's set of open databases, and let it own itself.
     1868    // It will dispatch back to the main thread later to finalize deleting itself.
     1869    m_owningPointerForClose = m_server.closeAndTakeUniqueIDBDatabase(*this);
    18511870
    18521871    // Have the database unconditionally delete itself on the database task queue.
    18531872    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performUnconditionalDeleteBackingStore));
    1854 
    1855     // Remove the database from the IDBServer's set of open databases.
    1856     // If there is no in-progress background thread activity for this database, it will be deleted here.
    1857     m_server.closeUniqueIDBDatabase(*this);
    18581873}
    18591874
  • trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h

    r218803 r219298  
    4343#include <wtf/HashSet.h>
    4444#include <wtf/ListHashSet.h>
    45 #include <wtf/Ref.h>
    46 #include <wtf/ThreadSafeRefCounted.h>
    4745
    4846namespace JSC {
     
    7573typedef Function<void(const IDBError&, uint64_t)> CountCallback;
    7674
    77 class UniqueIDBDatabase : public ThreadSafeRefCounted<UniqueIDBDatabase> {
     75class UniqueIDBDatabase {
    7876public:
    79     static Ref<UniqueIDBDatabase> create(IDBServer& server, const IDBDatabaseIdentifier& identifier)
    80     {
    81         return adoptRef(*new UniqueIDBDatabase(server, identifier));
    82     }
    83 
     77    UniqueIDBDatabase(IDBServer&, const IDBDatabaseIdentifier&);
     78    UniqueIDBDatabase(UniqueIDBDatabase&) = delete;
    8479    WEBCORE_EXPORT ~UniqueIDBDatabase();
    8580
     
    125120
    126121private:
    127     UniqueIDBDatabase(IDBServer&, const IDBDatabaseIdentifier&);
    128    
    129122    void handleDatabaseOperations();
    130123    void handleCurrentOperation();
     
    144137
    145138    void connectionClosedFromServer(UniqueIDBDatabaseConnection&);
     139
     140    void scheduleShutdownForClose();
    146141
    147142    // Database thread operations
     
    170165    void performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo&);
    171166    void performUnconditionalDeleteBackingStore();
     167    void shutdownForClose();
    172168
    173169    // Main thread callbacks
     
    192188    void didPerformActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBError&);
    193189    void didPerformUnconditionalDeleteBackingStore();
     190    void didShutdownForClose();
    194191
    195192    uint64_t storeCallbackOrFireError(ErrorCallback&&);
     
    266263    bool m_deleteBackingStoreInProgress { false };
    267264
    268     CrossThreadQueue<Function<void ()>> m_databaseQueue;
    269     CrossThreadQueue<Function<void ()>> m_databaseReplyQueue;
    270     std::atomic<uint64_t> m_queuedTaskCount { 0 };
     265    CrossThreadQueue<CrossThreadTask> m_databaseQueue;
     266    CrossThreadQueue<CrossThreadTask> m_databaseReplyQueue;
    271267
    272268    bool m_hardClosedForUserDelete { false };
    273     RefPtr<UniqueIDBDatabase> m_hardCloseProtector;
    274 
    275     HashMap<IDBResourceIdentifier, RefPtr<UniqueIDBDatabase>> m_prefetchProtectors;
     269    std::unique_ptr<UniqueIDBDatabase> m_owningPointerForClose;
     270
     271    HashSet<IDBResourceIdentifier> m_cursorPrefetches;
    276272};
    277273
Note: See TracChangeset for help on using the changeset viewer.