diff options
Diffstat (limited to 'Source/WebCore/Modules/webdatabase/DatabaseThread.cpp')
-rw-r--r-- | Source/WebCore/Modules/webdatabase/DatabaseThread.cpp | 177 |
1 files changed, 46 insertions, 131 deletions
diff --git a/Source/WebCore/Modules/webdatabase/DatabaseThread.cpp b/Source/WebCore/Modules/webdatabase/DatabaseThread.cpp index 7ee764ca0..0dde5f726 100644 --- a/Source/WebCore/Modules/webdatabase/DatabaseThread.cpp +++ b/Source/WebCore/Modules/webdatabase/DatabaseThread.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,25 +29,17 @@ #include "config.h" #include "DatabaseThread.h" -#if ENABLE(SQL_DATABASE) - #include "Database.h" #include "DatabaseTask.h" #include "Logging.h" -#include "SQLTransactionClient.h" +#include "SQLTransaction.h" #include "SQLTransactionCoordinator.h" #include <wtf/AutodrainedPool.h> namespace WebCore { DatabaseThread::DatabaseThread() - : m_threadID(0) -#if PLATFORM(IOS) - , m_paused(false) -#endif - , m_transactionClient(adoptPtr(new SQLTransactionClient())) - , m_transactionCoordinator(adoptPtr(new SQLTransactionCoordinator())) - , m_cleanupSync(0) + : m_transactionCoordinator(std::make_unique<SQLTransactionCoordinator>()) { m_selfRef = this; } @@ -66,7 +58,7 @@ DatabaseThread::~DatabaseThread() bool DatabaseThread::start() { - MutexLocker lock(m_threadCreationMutex); + LockHolder lock(m_threadCreationMutex); if (m_threadID) return true; @@ -76,13 +68,10 @@ bool DatabaseThread::start() return m_threadID; } -void DatabaseThread::requestTermination(DatabaseTaskSynchronizer *cleanupSync) +void DatabaseThread::requestTermination(DatabaseTaskSynchronizer* cleanupSync) { m_cleanupSync = cleanupSync; LOG(StorageAPI, "DatabaseThread %p was asked to terminate\n", this); -#if PLATFORM(IOS) - m_pausedQueue.kill(); -#endif m_queue.kill(); } @@ -104,99 +93,18 @@ void DatabaseThread::databaseThreadStart(void* vDatabaseThread) dbThread->databaseThread(); } -#if PLATFORM(IOS) -class DatabaseUnpauseTask : public DatabaseTask { -public: - static std::unique_ptr<DatabaseUnpauseTask> create(DatabaseThread* thread) - { - return std::unique_ptr<DatabaseUnpauseTask>(new DatabaseUnpauseTask(thread)); - } - - virtual bool shouldPerformWhilePaused() const - { - // Since we're not locking the DatabaseThread::m_paused in the main database thread loop, it's possible that - // a DatabaseUnpauseTask might be added to the m_pausedQueue and performed from within ::handlePausedQueue. - // To protect against this, we allow it to be performed even if the database is paused. - // If the thread is paused when it is being performed, the tasks from the paused queue will simply be - // requeued instead of performed. - return true; - } - -private: - DatabaseUnpauseTask(DatabaseThread* thread) - : DatabaseTask(0, 0) - , m_thread(thread) - {} - - virtual void doPerformTask() - { - m_thread->handlePausedQueue(); - } -#if !LOG_DISABLED - virtual const char* debugTaskName() const { return "DatabaseUnpauseTask"; } -#endif - - DatabaseThread* m_thread; -}; - - -void DatabaseThread::setPaused(bool paused) -{ - if (m_paused == paused) - return; - - MutexLocker pausedLocker(m_pausedMutex); - m_paused = paused; - if (!m_paused) - scheduleTask(DatabaseUnpauseTask::create(this)); -} - -void DatabaseThread::handlePausedQueue() -{ - Vector<std::unique_ptr<DatabaseTask> > pausedTasks; - while (auto task = m_pausedQueue.tryGetMessage()) - pausedTasks.append(std::move(task)); - - for (unsigned i = 0; i < pausedTasks.size(); ++i) { - AutodrainedPool pool; - - std::unique_ptr<DatabaseTask> task(pausedTasks[i].release()); - { - MutexLocker pausedLocker(m_pausedMutex); - if (m_paused) { - m_pausedQueue.append(std::move(task)); - continue; - } - } - - if (terminationRequested()) - break; - - task->performTask(); - } -} -#endif //PLATFORM(IOS) - - void DatabaseThread::databaseThread() { { // Wait for DatabaseThread::start() to complete. - MutexLocker lock(m_threadCreationMutex); + LockHolder lock(m_threadCreationMutex); LOG(StorageAPI, "Started DatabaseThread %p", this); } while (auto task = m_queue.waitForMessage()) { AutodrainedPool pool; -#if PLATFORM(IOS) - if (!m_paused || task->shouldPerformWhilePaused()) - task->performTask(); - else - m_pausedQueue.append(std::move(task)); -#else task->performTask(); -#endif } // Clean up the list of all pending transactions on this database thread @@ -206,69 +114,76 @@ void DatabaseThread::databaseThread() // Close the databases that we ran transactions on. This ensures that if any transactions are still open, they are rolled back and we don't leave the database in an // inconsistent or locked state. - if (m_openDatabaseSet.size() > 0) { - // As the call to close will modify the original set, we must take a copy to iterate over. - DatabaseSet openSetCopy; - openSetCopy.swap(m_openDatabaseSet); - DatabaseSet::iterator end = openSetCopy.end(); - for (DatabaseSet::iterator it = openSetCopy.begin(); it != end; ++it) - (*it).get()->close(); + DatabaseSet openSetCopy; + { + LockHolder lock(m_openDatabaseSetMutex); + if (m_openDatabaseSet.size() > 0) { + // As the call to close will modify the original set, we must take a copy to iterate over. + openSetCopy.swap(m_openDatabaseSet); + } } + for (auto& openDatabase : openSetCopy) + openDatabase->performClose(); + // Detach the thread so its resources are no longer of any concern to anyone else detachThread(m_threadID); DatabaseTaskSynchronizer* cleanupSync = m_cleanupSync; // Clear the self refptr, possibly resulting in deletion - m_selfRef = 0; + m_selfRef = nullptr; if (cleanupSync) // Someone wanted to know when we were done cleaning up. cleanupSync->taskCompleted(); } -void DatabaseThread::recordDatabaseOpen(DatabaseBackend* database) +void DatabaseThread::recordDatabaseOpen(Database& database) { + LockHolder lock(m_openDatabaseSetMutex); + ASSERT(currentThread() == m_threadID); - ASSERT(database); - ASSERT(!m_openDatabaseSet.contains(database)); - m_openDatabaseSet.add(database); + ASSERT(!m_openDatabaseSet.contains(&database)); + m_openDatabaseSet.add(&database); } -void DatabaseThread::recordDatabaseClosed(DatabaseBackend* database) +void DatabaseThread::recordDatabaseClosed(Database& database) { + LockHolder lock(m_openDatabaseSetMutex); + ASSERT(currentThread() == m_threadID); - ASSERT(database); - ASSERT(m_queue.killed() || m_openDatabaseSet.contains(database)); - m_openDatabaseSet.remove(database); + ASSERT(m_queue.killed() || m_openDatabaseSet.contains(&database)); + m_openDatabaseSet.remove(&database); } -void DatabaseThread::scheduleTask(std::unique_ptr<DatabaseTask> task) +void DatabaseThread::scheduleTask(std::unique_ptr<DatabaseTask>&& task) { ASSERT(!task->hasSynchronizer() || task->hasCheckedForTermination()); - m_queue.append(std::move(task)); + m_queue.append(WTFMove(task)); } -void DatabaseThread::scheduleImmediateTask(std::unique_ptr<DatabaseTask> task) +void DatabaseThread::scheduleImmediateTask(std::unique_ptr<DatabaseTask>&& task) { ASSERT(!task->hasSynchronizer() || task->hasCheckedForTermination()); - m_queue.prepend(std::move(task)); + m_queue.prepend(WTFMove(task)); } -class SameDatabasePredicate { -public: - SameDatabasePredicate(const DatabaseBackend* database) : m_database(database) { } - bool operator()(const DatabaseTask& task) const { return task.database() == m_database; } -private: - const DatabaseBackend* m_database; -}; +void DatabaseThread::unscheduleDatabaseTasks(Database& database) +{ + // The thread loop is running, sp some tasks for this database may still be executed. This is unavoidable. + m_queue.removeIf([&database] (const DatabaseTask& task) { + return &task.database() == &database; + }); +} -void DatabaseThread::unscheduleDatabaseTasks(DatabaseBackend* database) +bool DatabaseThread::hasPendingDatabaseActivity() const { - // Note that the thread loop is running, so some tasks for the database - // may still be executed. This is unavoidable. - SameDatabasePredicate predicate(database); - m_queue.removeIf(predicate); + LockHolder lock(m_openDatabaseSetMutex); + for (auto& database : m_openDatabaseSet) { + if (database->hasPendingCreationEvent() || database->hasPendingTransaction()) + return true; + } + return false; } + } // namespace WebCore -#endif |