1/* 2 * Copyright (C) 2009 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. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "LoaderRunLoopCF.h" 28 29#if USE(CFNETWORK) 30 31#include <CoreFoundation/CoreFoundation.h> 32#include <condition_variable> 33#include <limits> 34#include <wtf/AutodrainedPool.h> 35#include <wtf/MainThread.h> 36#include <wtf/NeverDestroyed.h> 37#include <wtf/Threading.h> 38 39namespace WebCore { 40 41static CFRunLoopRef loaderRunLoopObject = 0; 42 43static std::mutex& loaderRunLoopMutex() 44{ 45 static NeverDestroyed<std::mutex> mutex; 46 47 return mutex; 48} 49 50static std::condition_variable& loaderRunLoopConditionVariable() 51{ 52 static NeverDestroyed<std::condition_variable> conditionVariable; 53 54 return conditionVariable; 55} 56 57static void emptyPerform(void*) 58{ 59} 60 61static void runLoaderThread(void*) 62{ 63 { 64 std::lock_guard<std::mutex> lock(loaderRunLoopMutex()); 65 66 loaderRunLoopObject = CFRunLoopGetCurrent(); 67 68 // Must add a source to the run loop to prevent CFRunLoopRun() from exiting. 69 CFRunLoopSourceContext ctxt = {0, (void*)1 /*must be non-null*/, 0, 0, 0, 0, 0, 0, 0, emptyPerform}; 70 CFRunLoopSourceRef bogusSource = CFRunLoopSourceCreate(0, 0, &ctxt); 71 CFRunLoopAddSource(loaderRunLoopObject, bogusSource, kCFRunLoopDefaultMode); 72 73 loaderRunLoopConditionVariable().notify_one(); 74 } 75 76 SInt32 result; 77 do { 78 AutodrainedPool pool; 79 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, std::numeric_limits<double>::max(), true); 80 } while (result != kCFRunLoopRunStopped && result != kCFRunLoopRunFinished); 81} 82 83CFRunLoopRef loaderRunLoop() 84{ 85 ASSERT(isMainThread()); 86 87 std::unique_lock<std::mutex> lock(loaderRunLoopMutex()); 88 89 if (!loaderRunLoopObject) { 90 createThread(runLoaderThread, 0, "WebCore: CFNetwork Loader"); 91 92 loaderRunLoopConditionVariable().wait(lock, [] { return loaderRunLoopObject; }); 93 } 94 95 return loaderRunLoopObject; 96} 97 98} // namespace WebCore 99 100#endif // USE(CFNETWORK) 101