DeferredWorkTimer.h
1 /* 2 * Copyright (C) 2017-2020 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 #pragma once 27 28 #include "JSRunLoopTimer.h" 29 #include "Strong.h" 30 31 #include <wtf/Deque.h> 32 #include <wtf/HashMap.h> 33 #include <wtf/Lock.h> 34 #include <wtf/Vector.h> 35 36 namespace JSC { 37 38 class JSPromise; 39 class VM; 40 class JSCell; 41 42 class JS_EXPORT_PRIVATE DeferredWorkTimer final : public JSRunLoopTimer { 43 public: 44 using Base = JSRunLoopTimer; 45 46 void doWork(VM&) final; 47 48 using Ticket = JSObject*; 49 void addPendingWork(VM&, Ticket, Vector<Strong<JSCell>>&& dependencies); 50 bool hasPendingWork(Ticket); 51 bool hasDependancyInPendingWork(Ticket, JSCell* dependency); 52 bool cancelPendingWork(Ticket); 53 54 // If the script execution owner your ticket is associated with gets canceled 55 // the Task will not be called and will be deallocated. So it's important 56 // to make sure your memory ownership model won't leak memory when 57 // this occurs. The easiest way is to make sure everything is either owned 58 // by a GC'd value in dependencies or by the Task lambda. 59 using Task = Function<void()>; 60 void scheduleWorkSoon(Ticket, Task&&); 61 void didResumeScriptExecutionOwner(); 62 63 void stopRunningTasks() { m_runTasks = false; } 64 void runRunLoop(); 65 66 static Ref<DeferredWorkTimer> create(VM& vm) { return adoptRef(*new DeferredWorkTimer(vm)); } 67 private: 68 DeferredWorkTimer(VM&); 69 70 Lock m_taskLock; 71 bool m_runTasks { true }; 72 bool m_shouldStopRunLoopWhenAllTicketsFinish { false }; 73 bool m_currentlyRunningTask { false }; 74 Deque<std::tuple<Ticket, Task>> m_tasks; 75 struct TicketData { 76 Vector<Strong<JSCell>> dependencies; 77 Strong<JSObject> scriptExecutionOwner; 78 }; 79 HashMap<Ticket, TicketData> m_pendingTickets; 80 }; 81 82 } // namespace JSC