DatabaseThread::~DatabaseThread()
{
ASSERT(m_openDatabaseSet.isEmpty());
- // Oilpan: The database thread must have finished its cleanup tasks before
- // the following clear(). Otherwise, WebThread destructor blocks the caller
- // thread, and causes a deadlock with ThreadState cleanup.
- // DatabaseContext::stop() asks the database thread to close all of
- // databases, and wait until GC heap cleanup of the database thread. So we
- // can safely destruct WebThread here.
- m_thread.clear();
+ ASSERT(!m_thread);
}
void DatabaseThread::trace(Visitor* visitor)
{
if (m_thread)
return;
- m_thread = adoptPtr(Platform::current()->createThread("WebCore: Database"));
+ m_thread = WebThreadSupportingGC::create("WebCore: Database");
m_thread->postTask(new Task(WTF::bind(&DatabaseThread::setupDatabaseThread, this)));
}
void DatabaseThread::setupDatabaseThread()
{
- m_pendingGCRunner = adoptPtr(new PendingGCRunner);
- m_messageLoopInterruptor = adoptPtr(new MessageLoopInterruptor(m_thread.get()));
- m_thread->addTaskObserver(m_pendingGCRunner.get());
- ThreadState::attach();
- ThreadState::current()->addInterruptor(m_messageLoopInterruptor.get());
+ m_thread->attachGC();
}
-void DatabaseThread::requestTermination(TaskSynchronizer *cleanupSync)
+void DatabaseThread::terminate()
{
- MutexLocker lock(m_terminationRequestedMutex);
- ASSERT(!m_terminationRequested);
- m_terminationRequested = true;
- m_cleanupSync = cleanupSync;
- WTF_LOG(StorageAPI, "DatabaseThread %p was asked to terminate\n", this);
- m_thread->postTask(new Task(WTF::bind(&DatabaseThread::cleanupDatabaseThread, this)));
+ TaskSynchronizer sync;
+ {
+ MutexLocker lock(m_terminationRequestedMutex);
+ ASSERT(!m_terminationRequested);
+ m_terminationRequested = true;
+ m_cleanupSync = &sync;
+ WTF_LOG(StorageAPI, "DatabaseThread %p was asked to terminate\n", this);
+ m_thread->postTask(new Task(WTF::bind(&DatabaseThread::cleanupDatabaseThread, this)));
+ }
+ sync.waitForTaskCompletion();
+ // The WebThread destructor blocks until all the tasks of the database
+ // thread are processed. However, it shouldn't block at all because
+ // the database thread has already finished processing the cleanup task.
+ m_thread.clear();
}
-bool DatabaseThread::terminationRequested(TaskSynchronizer* taskSynchronizer) const
+bool DatabaseThread::terminationRequested() const
{
-#if ENABLE(ASSERT)
- if (taskSynchronizer)
- taskSynchronizer->setHasCheckedForTermination();
-#endif
-
MutexLocker lock(m_terminationRequestedMutex);
return m_terminationRequested;
}
// 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.
- WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> > openSetCopy;
+ WillBeHeapHashSet<RefPtrWillBeMember<Database> > openSetCopy;
openSetCopy.swap(m_openDatabaseSet);
- WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> >::iterator end = openSetCopy.end();
- for (WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> >::iterator it = openSetCopy.begin(); it != end; ++it)
+ WillBeHeapHashSet<RefPtrWillBeMember<Database> >::iterator end = openSetCopy.end();
+ for (WillBeHeapHashSet<RefPtrWillBeMember<Database> >::iterator it = openSetCopy.begin(); it != end; ++it)
(*it)->close();
}
void DatabaseThread::cleanupDatabaseThreadCompleted()
{
- ThreadState::current()->removeInterruptor(m_messageLoopInterruptor.get());
- ThreadState::detach();
- // We need to unregister PendingGCRunner before finising this task to avoid
- // PendingGCRunner::didProcessTask accesses dead ThreadState.
- m_thread->removeTaskObserver(m_pendingGCRunner.get());
-
+ m_thread->detachGC();
if (m_cleanupSync) // Someone wanted to know when we were done cleaning up.
m_cleanupSync->taskCompleted();
}
-void DatabaseThread::recordDatabaseOpen(DatabaseBackend* database)
+void DatabaseThread::recordDatabaseOpen(Database* database)
{
ASSERT(isDatabaseThread());
ASSERT(database);
m_openDatabaseSet.add(database);
}
-void DatabaseThread::recordDatabaseClosed(DatabaseBackend* database)
+void DatabaseThread::recordDatabaseClosed(Database* database)
{
ASSERT(isDatabaseThread());
ASSERT(database);
m_openDatabaseSet.remove(database);
}
-bool DatabaseThread::isDatabaseOpen(DatabaseBackend* database)
+bool DatabaseThread::isDatabaseOpen(Database* database)
{
ASSERT(isDatabaseThread());
ASSERT(database);
void DatabaseThread::scheduleTask(PassOwnPtr<DatabaseTask> task)
{
ASSERT(m_thread);
- ASSERT(!task->hasSynchronizer() || task->hasCheckedForTermination());
+ ASSERT(!terminationRequested());
// WebThread takes ownership of the task.
m_thread->postTask(task.leakPtr());
}