• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IDBPendingTransactionMonitor()35 IDBPendingTransactionMonitor::IDBPendingTransactionMonitor()
36 {
37 }
38 
~IDBPendingTransactionMonitor()39 IDBPendingTransactionMonitor::~IDBPendingTransactionMonitor()
40 {
41 }
42 
addNewTransaction(IDBTransaction & transaction)43 void IDBPendingTransactionMonitor::addNewTransaction(IDBTransaction& transaction)
44 {
45     m_transactions.append(&transaction);
46 }
47 
deactivateNewTransactions()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:
create()60     static PassRefPtr<IDBDisposerDispatcher> create() { return adoptRef(new IDBDisposerDispatcher()); }
61 
62 private:
IDBDisposerDispatcher()63     IDBDisposerDispatcher() { }
64 
65     template<typename Owner, typename Target>
66     class Disposer {
67     public:
create(Owner & owner,Target & target)68         static PassOwnPtr<Disposer> create(Owner& owner, Target& target) { return adoptPtr(new Disposer(owner, target)); }
~Disposer()69         ~Disposer()
70         {
71             if (!m_isDisabled)
72                 m_target.dispose();
73         }
setDisabled()74         void setDisabled() { m_isDisabled = true; }
75 
76     private:
Disposer(Owner & owner,Target & target)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:
registerTarget(IDBDisposerDispatcher & dispatcher,Target & target)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 
unregisterTarget(IDBDisposerDispatcher & dispatcher,Target & target)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 
registerRequest(IDBRequest & request)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 
unregisterRequest(IDBRequest & request)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 
registerCursor(IDBCursor & cursor)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 
unregisterCursor(IDBCursor & cursor)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