1/* 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "StorageThread.h" 28 29#include "StorageAreaSync.h" 30#include <wtf/AutodrainedPool.h> 31#include <wtf/HashSet.h> 32#include <wtf/MainThread.h> 33 34namespace WebCore { 35 36static HashSet<StorageThread*>& activeStorageThreads() 37{ 38 ASSERT(isMainThread()); 39 DEFINE_STATIC_LOCAL(HashSet<StorageThread*>, threads, ()); 40 return threads; 41} 42 43PassOwnPtr<StorageThread> StorageThread::create() 44{ 45 return adoptPtr(new StorageThread); 46} 47 48StorageThread::StorageThread() 49 : m_threadID(0) 50{ 51 ASSERT(isMainThread()); 52} 53 54StorageThread::~StorageThread() 55{ 56 ASSERT(isMainThread()); 57 ASSERT(!m_threadID); 58} 59 60bool StorageThread::start() 61{ 62 ASSERT(isMainThread()); 63 if (!m_threadID) 64 m_threadID = createThread(StorageThread::threadEntryPointCallback, this, "WebCore: LocalStorage"); 65 activeStorageThreads().add(this); 66 return m_threadID; 67} 68 69void StorageThread::threadEntryPointCallback(void* thread) 70{ 71 static_cast<StorageThread*>(thread)->threadEntryPoint(); 72} 73 74void StorageThread::threadEntryPoint() 75{ 76 ASSERT(!isMainThread()); 77 78 while (OwnPtr<Function<void ()> > function = m_queue.waitForMessage()) { 79 AutodrainedPool pool; 80 (*function)(); 81 } 82} 83 84void StorageThread::dispatch(const Function<void ()>& function) 85{ 86 ASSERT(isMainThread()); 87 ASSERT(!m_queue.killed() && m_threadID); 88 m_queue.append(adoptPtr(new Function<void ()>(function))); 89} 90 91void StorageThread::terminate() 92{ 93 ASSERT(isMainThread()); 94 ASSERT(!m_queue.killed() && m_threadID); 95 activeStorageThreads().remove(this); 96 // Even in weird, exceptional cases, don't wait on a nonexistent thread to terminate. 97 if (!m_threadID) 98 return; 99 100 m_queue.append(adoptPtr(new Function<void ()>((bind(&StorageThread::performTerminate, this))))); 101 waitForThreadCompletion(m_threadID); 102 ASSERT(m_queue.killed()); 103 m_threadID = 0; 104} 105 106void StorageThread::performTerminate() 107{ 108 ASSERT(!isMainThread()); 109 m_queue.kill(); 110} 111 112void StorageThread::releaseFastMallocFreeMemoryInAllThreads() 113{ 114 HashSet<StorageThread*>& threads = activeStorageThreads(); 115 116 for (HashSet<StorageThread*>::iterator it = threads.begin(), end = threads.end(); it != end; ++it) 117 (*it)->dispatch(bind(WTF::releaseFastMallocFreeMemory)); 118} 119 120} 121