summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/webdatabase/DatabaseThread.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebCore/Modules/webdatabase/DatabaseThread.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-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.cpp152
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