1 /* 2 * Copyright (C) 2010 Google 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 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "modules/indexeddb/IDBPendingTransactionMonitor.h" 28 29 #include "modules/indexeddb/IDBCursor.h" 30 #include "modules/indexeddb/IDBRequest.h" 31 #include "modules/indexeddb/IDBTransaction.h" 32 33 namespace blink { 34 35 IDBPendingTransactionMonitor::IDBPendingTransactionMonitor() 36 { 37 } 38 39 IDBPendingTransactionMonitor::~IDBPendingTransactionMonitor() 40 { 41 } 42 43 void IDBPendingTransactionMonitor::addNewTransaction(IDBTransaction& transaction) 44 { 45 m_transactions.append(&transaction); 46 } 47 48 void IDBPendingTransactionMonitor::deactivateNewTransactions() 49 { 50 for (size_t i = 0; i < m_transactions.size(); ++i) 51 m_transactions[i]->setActive(false); 52 // FIXME: Exercise this call to clear() in a layout test. 53 m_transactions.clear(); 54 } 55 56 // IDBDisposerDispatcher should be RefCounted because it should outlive all of 57 // target objects. 58 class IDBDisposerDispatcher: public RefCounted<IDBDisposerDispatcher> { 59 public: 60 static PassRefPtr<IDBDisposerDispatcher> create() { return adoptRef(new IDBDisposerDispatcher()); } 61 62 private: 63 IDBDisposerDispatcher() { } 64 65 template<typename Owner, typename Target> 66 class Disposer { 67 public: 68 static PassOwnPtr<Disposer> create(Owner& owner, Target& target) { return adoptPtr(new Disposer(owner, target)); } 69 ~Disposer() 70 { 71 if (!m_isDisabled) 72 m_target.dispose(); 73 } 74 void setDisabled() { m_isDisabled = true; } 75 76 private: 77 Disposer(Owner& owner, Target& target) 78 : m_owner(owner) 79 , m_target(target) 80 , m_isDisabled(false) 81 { 82 } 83 84 RefPtr<Owner> m_owner; 85 Target& m_target; 86 bool m_isDisabled; 87 }; 88 89 template<typename Target> 90 class DisposerMap { 91 DISALLOW_ALLOCATION(); 92 public: 93 void registerTarget(IDBDisposerDispatcher& dispatcher, Target& target) 94 { 95 ASSERT(!m_disposerMap.contains(&target)); 96 m_disposerMap.add(&target, Disposer<IDBDisposerDispatcher, Target>::create(dispatcher, target)); 97 } 98 99 void unregisterTarget(IDBDisposerDispatcher& dispatcher, Target& target) 100 { 101 // Skip this function if this is called in Target::dispose(). 102 if (ThreadState::current()->isSweepInProgress()) 103 return; 104 auto it = m_disposerMap.find(&target); 105 ASSERT(it != m_disposerMap.end()); 106 if (it == m_disposerMap.end()) 107 return; 108 // m_disposerMap.remove() will trigger ~Disposer. We should not call 109 // Target::dispose() in ~Disposer in this case. 110 it->value->setDisabled(); 111 m_disposerMap.remove(it); 112 } 113 114 private: 115 PersistentHeapHashMap<WeakMember<Target>, OwnPtr<Disposer<IDBDisposerDispatcher, Target>>> m_disposerMap; 116 }; 117 118 DisposerMap<IDBRequest> m_requests; 119 DisposerMap<IDBCursor> m_cursors; 120 friend class IDBPendingTransactionMonitor; 121 }; 122 123 void IDBPendingTransactionMonitor::registerRequest(IDBRequest& request) 124 { 125 if (!m_dispatcher) 126 m_dispatcher = IDBDisposerDispatcher::create(); 127 m_dispatcher->m_requests.registerTarget(*m_dispatcher, request); 128 } 129 130 void IDBPendingTransactionMonitor::unregisterRequest(IDBRequest& request) 131 { 132 // We should not unregister without registeration. 133 ASSERT(m_dispatcher); 134 m_dispatcher->m_requests.unregisterTarget(*m_dispatcher, request); 135 } 136 137 void IDBPendingTransactionMonitor::registerCursor(IDBCursor& cursor) 138 { 139 if (!m_dispatcher) 140 m_dispatcher = IDBDisposerDispatcher::create(); 141 m_dispatcher->m_cursors.registerTarget(*m_dispatcher, cursor); 142 } 143 144 void IDBPendingTransactionMonitor::unregisterCursor(IDBCursor& cursor) 145 { 146 // We should not unregister without registeration. 147 ASSERT(m_dispatcher); 148 m_dispatcher->m_cursors.unregisterTarget(*m_dispatcher, cursor); 149 } 150 151 } // namespace blink 152