diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebCore/Modules/webdatabase/DatabaseThread.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/WebCore/Modules/webdatabase/DatabaseThread.cpp')
-rw-r--r-- | Source/WebCore/Modules/webdatabase/DatabaseThread.cpp | 152 |
1 files changed, 112 insertions, 40 deletions
diff --git a/Source/WebCore/Modules/webdatabase/DatabaseThread.cpp b/Source/WebCore/Modules/webdatabase/DatabaseThread.cpp index cc2cf6f8e..7ee764ca0 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 Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Computer, 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,6 +29,8 @@ #include "config.h" #include "DatabaseThread.h" +#if ENABLE(SQL_DATABASE) + #include "Database.h" #include "DatabaseTask.h" #include "Logging.h" @@ -40,9 +42,12 @@ namespace WebCore { DatabaseThread::DatabaseThread() : m_threadID(0) - , m_transactionClient(std::make_unique<SQLTransactionClient>()) - , m_transactionCoordinator(std::make_unique<SQLTransactionCoordinator>()) - , m_cleanupSync(nullptr) +#if PLATFORM(IOS) + , m_paused(false) +#endif + , m_transactionClient(adoptPtr(new SQLTransactionClient())) + , m_transactionCoordinator(adoptPtr(new SQLTransactionCoordinator())) + , m_cleanupSync(0) { m_selfRef = this; } @@ -61,7 +66,7 @@ DatabaseThread::~DatabaseThread() bool DatabaseThread::start() { - LockHolder lock(m_threadCreationMutex); + MutexLocker lock(m_threadCreationMutex); if (m_threadID) return true; @@ -75,6 +80,9 @@ 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(); } @@ -96,18 +104,99 @@ 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. - LockHolder lock(m_threadCreationMutex); + MutexLocker 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 @@ -117,44 +206,37 @@ 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. - 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); - } + 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(); } - for (auto& openDatabase : openSetCopy) - openDatabase->close(); - // 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 = nullptr; + m_selfRef = 0; if (cleanupSync) // Someone wanted to know when we were done cleaning up. cleanupSync->taskCompleted(); } -void DatabaseThread::recordDatabaseOpen(Database* database) +void DatabaseThread::recordDatabaseOpen(DatabaseBackend* database) { - LockHolder lock(m_openDatabaseSetMutex); - ASSERT(currentThread() == m_threadID); ASSERT(database); ASSERT(!m_openDatabaseSet.contains(database)); m_openDatabaseSet.add(database); } -void DatabaseThread::recordDatabaseClosed(Database* database) +void DatabaseThread::recordDatabaseClosed(DatabaseBackend* database) { - LockHolder lock(m_openDatabaseSetMutex); - ASSERT(currentThread() == m_threadID); ASSERT(database); ASSERT(m_queue.killed() || m_openDatabaseSet.contains(database)); @@ -164,39 +246,29 @@ void DatabaseThread::recordDatabaseClosed(Database* database) void DatabaseThread::scheduleTask(std::unique_ptr<DatabaseTask> task) { ASSERT(!task->hasSynchronizer() || task->hasCheckedForTermination()); - m_queue.append(WTFMove(task)); + m_queue.append(std::move(task)); } void DatabaseThread::scheduleImmediateTask(std::unique_ptr<DatabaseTask> task) { ASSERT(!task->hasSynchronizer() || task->hasCheckedForTermination()); - m_queue.prepend(WTFMove(task)); + m_queue.prepend(std::move(task)); } class SameDatabasePredicate { public: - SameDatabasePredicate(const Database* database) : m_database(database) { } - bool operator()(const DatabaseTask& task) const { return &task.database() == m_database; } + SameDatabasePredicate(const DatabaseBackend* database) : m_database(database) { } + bool operator()(const DatabaseTask& task) const { return task.database() == m_database; } private: - const Database* m_database; + const DatabaseBackend* m_database; }; -void DatabaseThread::unscheduleDatabaseTasks(Database* database) +void DatabaseThread::unscheduleDatabaseTasks(DatabaseBackend* database) { // 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); } - -bool DatabaseThread::hasPendingDatabaseActivity() const -{ - LockHolder lock(m_openDatabaseSetMutex); - for (auto& database : m_openDatabaseSet) { - if (database->hasPendingCreationEvent() || database->hasPendingTransaction()) - return true; - } - return false; -} - } // namespace WebCore +#endif |