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 "LocalStorageThread.h"
28
29 #if ENABLE(DOM_STORAGE)
30
31 #include "LocalStorageTask.h"
32 #include "StorageAreaSync.h"
33
34 namespace WebCore {
35
create()36 PassRefPtr<LocalStorageThread> LocalStorageThread::create()
37 {
38 return adoptRef(new LocalStorageThread);
39 }
40
LocalStorageThread()41 LocalStorageThread::LocalStorageThread()
42 : m_threadID(0)
43 {
44 m_selfRef = this;
45 }
46
start()47 bool LocalStorageThread::start()
48 {
49 MutexLocker lock(m_threadCreationMutex);
50
51 if (m_threadID)
52 return true;
53
54 m_threadID = createThread(LocalStorageThread::localStorageThreadStart, this, "WebCore: LocalStorage");
55
56 return m_threadID;
57 }
58
localStorageThreadStart(void * thread)59 void* LocalStorageThread::localStorageThreadStart(void* thread)
60 {
61 return static_cast<LocalStorageThread*>(thread)->localStorageThread();
62 }
63
localStorageThread()64 void* LocalStorageThread::localStorageThread()
65 {
66 {
67 // Wait for LocalStorageThread::start() to complete.
68 MutexLocker lock(m_threadCreationMutex);
69 }
70
71 while (true) {
72 RefPtr<LocalStorageTask> task;
73 if (!m_queue.waitForMessage(task))
74 break;
75
76 task->performTask();
77 }
78
79 // Detach the thread so its resources are no longer of any concern to anyone else
80 detachThread(m_threadID);
81 m_threadID = 0;
82
83 // Clear the self refptr, possibly resulting in deletion
84 m_selfRef = 0;
85
86 return 0;
87 }
88
scheduleImport(PassRefPtr<StorageAreaSync> area)89 void LocalStorageThread::scheduleImport(PassRefPtr<StorageAreaSync> area)
90 {
91 ASSERT(!m_queue.killed() && m_threadID);
92 m_queue.append(LocalStorageTask::createImport(area));
93 }
94
scheduleSync(PassRefPtr<StorageAreaSync> area)95 void LocalStorageThread::scheduleSync(PassRefPtr<StorageAreaSync> area)
96 {
97 ASSERT(!m_queue.killed() && m_threadID);
98 m_queue.append(LocalStorageTask::createSync(area));
99 }
100
terminate()101 void LocalStorageThread::terminate()
102 {
103 ASSERT(isMainThread());
104
105 // Ideally we'd never be killing a thread that wasn't live, so ASSERT it.
106 // But if we do in a release build, make sure to not wait on a condition that will never get signalled
107 ASSERT(!m_queue.killed() && m_threadID);
108 if (!m_threadID)
109 return;
110
111 MutexLocker locker(m_terminateLock);
112
113 m_queue.append(LocalStorageTask::createTerminate(this));
114
115 m_terminateCondition.wait(m_terminateLock);
116 }
117
performTerminate()118 void LocalStorageThread::performTerminate()
119 {
120 ASSERT(!isMainThread());
121
122 m_queue.kill();
123
124 MutexLocker locker(m_terminateLock);
125 m_terminateCondition.signal();
126 }
127
128 }
129
130 #endif // ENABLE(DOM_STORAGE)
131
132