]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/MainThread.cpp
c7a6caa34451e3ef0aa314d76fea066acc9e1a49
[apple/javascriptcore.git] / wtf / MainThread.cpp
1 /*
2 * Copyright (C) 2007, 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 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30 #include "MainThread.h"
31
32 #include "StdLibExtras.h"
33 #include "Threading.h"
34 #include "Vector.h"
35
36 namespace WTF {
37
38 struct FunctionWithContext {
39 MainThreadFunction* function;
40 void* context;
41 ThreadCondition* syncFlag;
42
43 FunctionWithContext(MainThreadFunction* function = 0, void* context = 0, ThreadCondition* syncFlag = 0)
44 : function(function)
45 , context(context)
46 , syncFlag(syncFlag)
47 {
48 }
49 };
50
51 typedef Vector<FunctionWithContext> FunctionQueue;
52
53 static bool callbacksPaused; // This global variable is only accessed from main thread.
54
55 Mutex& mainThreadFunctionQueueMutex()
56 {
57 DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
58 return staticMutex;
59 }
60
61 static FunctionQueue& functionQueue()
62 {
63 DEFINE_STATIC_LOCAL(FunctionQueue, staticFunctionQueue, ());
64 return staticFunctionQueue;
65 }
66
67 #if !PLATFORM(WIN)
68 void initializeMainThread()
69 {
70 mainThreadFunctionQueueMutex();
71 }
72 #endif
73
74 void dispatchFunctionsFromMainThread()
75 {
76 ASSERT(isMainThread());
77
78 if (callbacksPaused)
79 return;
80
81 FunctionQueue queueCopy;
82 {
83 MutexLocker locker(mainThreadFunctionQueueMutex());
84 queueCopy.swap(functionQueue());
85 }
86
87 for (unsigned i = 0; i < queueCopy.size(); ++i) {
88 FunctionWithContext& invocation = queueCopy[i];
89 invocation.function(invocation.context);
90 if (invocation.syncFlag)
91 invocation.syncFlag->signal();
92 }
93 }
94
95 void callOnMainThread(MainThreadFunction* function, void* context)
96 {
97 ASSERT(function);
98
99 {
100 MutexLocker locker(mainThreadFunctionQueueMutex());
101 functionQueue().append(FunctionWithContext(function, context));
102 }
103
104 scheduleDispatchFunctionsOnMainThread();
105 }
106
107 void callOnMainThreadAndWait(MainThreadFunction* function, void* context)
108 {
109 ASSERT(function);
110
111 if (isMainThread()) {
112 function(context);
113 return;
114 }
115
116 ThreadCondition syncFlag;
117 Mutex conditionMutex;
118
119 {
120 MutexLocker locker(mainThreadFunctionQueueMutex());
121 functionQueue().append(FunctionWithContext(function, context, &syncFlag));
122 conditionMutex.lock();
123 }
124
125 scheduleDispatchFunctionsOnMainThread();
126 syncFlag.wait(conditionMutex);
127 }
128
129 void setMainThreadCallbacksPaused(bool paused)
130 {
131 ASSERT(isMainThread());
132
133 if (callbacksPaused == paused)
134 return;
135
136 callbacksPaused = paused;
137
138 if (!callbacksPaused)
139 scheduleDispatchFunctionsOnMainThread();
140 }
141
142 } // namespace WTF