JavaScriptCore/wtf/gtk/ThreadingGtk.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
       
     3  * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
       
     4  *
       
     5  * Redistribution and use in source and binary forms, with or without
       
     6  * modification, are permitted provided that the following conditions
       
     7  * are met:
       
     8  *
       
     9  * 1.  Redistributions of source code must retain the above copyright
       
    10  *     notice, this list of conditions and the following disclaimer.
       
    11  * 2.  Redistributions in binary form must reproduce the above copyright
       
    12  *     notice, this list of conditions and the following disclaimer in the
       
    13  *     documentation and/or other materials provided with the distribution.
       
    14  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
       
    15  *     its contributors may be used to endorse or promote products derived
       
    16  *     from this software without specific prior written permission.
       
    17  *
       
    18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
       
    19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
       
    22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    28  */
       
    29 
       
    30 #include "config.h"
       
    31 #include "Threading.h"
       
    32 
       
    33 #if !USE(PTHREADS)
       
    34 
       
    35 #include "CurrentTime.h"
       
    36 #include "HashMap.h"
       
    37 #include "MainThread.h"
       
    38 #include "RandomNumberSeed.h"
       
    39 #include <wtf/StdLibExtras.h>
       
    40 
       
    41 #include <glib.h>
       
    42 #include <limits.h>
       
    43 
       
    44 namespace WTF {
       
    45 
       
    46 typedef HashMap<ThreadIdentifier, GThread*> ThreadMap;
       
    47 
       
    48 static Mutex* atomicallyInitializedStaticMutex;
       
    49 
       
    50 static Mutex& threadMapMutex()
       
    51 {
       
    52     DEFINE_STATIC_LOCAL(Mutex, mutex, ());
       
    53     return mutex;
       
    54 }
       
    55 
       
    56 void initializeThreading()
       
    57 {
       
    58     if (!g_thread_supported())
       
    59         g_thread_init(NULL);
       
    60     ASSERT(g_thread_supported());
       
    61 
       
    62     if (!atomicallyInitializedStaticMutex) {
       
    63         atomicallyInitializedStaticMutex = new Mutex;
       
    64         threadMapMutex();
       
    65         initializeRandomNumberGenerator();
       
    66     }
       
    67 }
       
    68 
       
    69 void lockAtomicallyInitializedStaticMutex()
       
    70 {
       
    71     ASSERT(atomicallyInitializedStaticMutex);
       
    72     atomicallyInitializedStaticMutex->lock();
       
    73 }
       
    74 
       
    75 void unlockAtomicallyInitializedStaticMutex()
       
    76 {
       
    77     atomicallyInitializedStaticMutex->unlock();
       
    78 }
       
    79 
       
    80 static ThreadMap& threadMap()
       
    81 {
       
    82     DEFINE_STATIC_LOCAL(ThreadMap, map, ());
       
    83     return map;
       
    84 }
       
    85 
       
    86 static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
       
    87 {
       
    88     MutexLocker locker(threadMapMutex());
       
    89 
       
    90     ThreadMap::iterator i = threadMap().begin();
       
    91     for (; i != threadMap().end(); ++i) {
       
    92         if (i->second == thread)
       
    93             return i->first;
       
    94     }
       
    95 
       
    96     return 0;
       
    97 }
       
    98 
       
    99 static ThreadIdentifier establishIdentifierForThread(GThread*& thread)
       
   100 {
       
   101     ASSERT(!identifierByGthreadHandle(thread));
       
   102 
       
   103     MutexLocker locker(threadMapMutex());
       
   104 
       
   105     static ThreadIdentifier identifierCount = 1;
       
   106 
       
   107     threadMap().add(identifierCount, thread);
       
   108 
       
   109     return identifierCount++;
       
   110 }
       
   111 
       
   112 static GThread* threadForIdentifier(ThreadIdentifier id)
       
   113 {
       
   114     MutexLocker locker(threadMapMutex());
       
   115 
       
   116     return threadMap().get(id);
       
   117 }
       
   118 
       
   119 static void clearThreadForIdentifier(ThreadIdentifier id)
       
   120 {
       
   121     MutexLocker locker(threadMapMutex());
       
   122 
       
   123     ASSERT(threadMap().contains(id));
       
   124 
       
   125     threadMap().remove(id);
       
   126 }
       
   127 
       
   128 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
       
   129 {
       
   130     GThread* thread;
       
   131     if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) {
       
   132         LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
       
   133         return 0;
       
   134     }
       
   135 
       
   136     ThreadIdentifier threadID = establishIdentifierForThread(thread);
       
   137     return threadID;
       
   138 }
       
   139 
       
   140 void initializeCurrentThreadInternal(const char*)
       
   141 {
       
   142 }
       
   143 
       
   144 int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
       
   145 {
       
   146     ASSERT(threadID);
       
   147 
       
   148     GThread* thread = threadForIdentifier(threadID);
       
   149 
       
   150     void* joinResult = g_thread_join(thread);
       
   151     if (result)
       
   152         *result = joinResult;
       
   153 
       
   154     clearThreadForIdentifier(threadID);
       
   155     return 0;
       
   156 }
       
   157 
       
   158 void detachThread(ThreadIdentifier)
       
   159 {
       
   160 }
       
   161 
       
   162 ThreadIdentifier currentThread()
       
   163 {
       
   164     GThread* currentThread = g_thread_self();
       
   165     if (ThreadIdentifier id = identifierByGthreadHandle(currentThread))
       
   166         return id;
       
   167     return establishIdentifierForThread(currentThread);
       
   168 }
       
   169 
       
   170 Mutex::Mutex()
       
   171     : m_mutex(g_mutex_new())
       
   172 {
       
   173 }
       
   174 
       
   175 Mutex::~Mutex()
       
   176 {
       
   177 }
       
   178 
       
   179 void Mutex::lock()
       
   180 {
       
   181     g_mutex_lock(m_mutex.get());
       
   182 }
       
   183 
       
   184 bool Mutex::tryLock()
       
   185 {
       
   186     return g_mutex_trylock(m_mutex.get());
       
   187 }
       
   188 
       
   189 void Mutex::unlock()
       
   190 {
       
   191     g_mutex_unlock(m_mutex.get());
       
   192 }
       
   193 
       
   194 ThreadCondition::ThreadCondition()
       
   195     : m_condition(g_cond_new())
       
   196 {
       
   197 }
       
   198 
       
   199 ThreadCondition::~ThreadCondition()
       
   200 {
       
   201 }
       
   202 
       
   203 void ThreadCondition::wait(Mutex& mutex)
       
   204 {
       
   205     g_cond_wait(m_condition.get(), mutex.impl().get());
       
   206 }
       
   207 
       
   208 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
       
   209 {
       
   210     // Time is in the past - return right away.
       
   211     if (absoluteTime < currentTime())
       
   212         return false;
       
   213     
       
   214     // Time is too far in the future for g_cond_timed_wait - wait forever.
       
   215     if (absoluteTime > INT_MAX) {
       
   216         wait(mutex);
       
   217         return true;
       
   218     }
       
   219 
       
   220     int timeSeconds = static_cast<int>(absoluteTime);
       
   221     int timeMicroseconds = static_cast<int>((absoluteTime - timeSeconds) * 1000000.0);
       
   222     
       
   223     GTimeVal targetTime;
       
   224     targetTime.tv_sec = timeSeconds;
       
   225     targetTime.tv_usec = timeMicroseconds;
       
   226 
       
   227     return g_cond_timed_wait(m_condition.get(), mutex.impl().get(), &targetTime);
       
   228 }
       
   229 
       
   230 void ThreadCondition::signal()
       
   231 {
       
   232     g_cond_signal(m_condition.get());
       
   233 }
       
   234 
       
   235 void ThreadCondition::broadcast()
       
   236 {
       
   237     g_cond_broadcast(m_condition.get());
       
   238 }
       
   239 
       
   240 
       
   241 }
       
   242 
       
   243 #endif // !USE(PTHREADS)