1 /* 2 * Copyright (C) 2011 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef ThreadRestrictionVerifier_h 32 #define ThreadRestrictionVerifier_h 33 34 #include "wtf/Assertions.h" 35 #include "wtf/Threading.h" 36 #include "wtf/ThreadingPrimitives.h" 37 38 #if HAVE(DISPATCH_H) 39 #include <dispatch/dispatch.h> 40 #endif 41 42 #ifndef NDEBUG 43 44 namespace WTF { 45 46 // Verifies that a class is used in a way that respects its lack of thread-safety. 47 // The default mode is to verify that the object will only be used on a single thread. The 48 // thread gets captured when setShared(true) is called. 49 // The mode may be changed by calling useMutexMode (or turnOffVerification). 50 class ThreadRestrictionVerifier { 51 public: 52 ThreadRestrictionVerifier() 53 : m_mode(SingleThreadVerificationMode) 54 , m_shared(false) 55 , m_owningThread(0) 56 , m_mutex(0) 57 #if HAVE(DISPATCH_H) 58 , m_owningQueue(0) 59 #endif 60 { 61 } 62 63 #if HAVE(DISPATCH_H) 64 ~ThreadRestrictionVerifier() 65 { 66 if (m_owningQueue) 67 dispatch_release(m_owningQueue); 68 } 69 #endif 70 71 void setMutexMode(Mutex& mutex) 72 { 73 m_mode = MutexVerificationMode; 74 m_mutex = &mutex; 75 } 76 77 #if HAVE(DISPATCH_H) 78 void setDispatchQueueMode(dispatch_queue_t queue) 79 { 80 m_mode = SingleDispatchQueueVerificationMode; 81 m_owningQueue = queue; 82 dispatch_retain(m_owningQueue); 83 } 84 #endif 85 86 void turnOffVerification() 87 { 88 m_mode = NoVerificationMode; 89 } 90 91 // Indicates that the object may (or may not) be owned by more than one place. 92 void setShared(bool shared) 93 { 94 #if !ASSERT_DISABLED 95 bool previouslyShared = m_shared; 96 #endif 97 m_shared = shared; 98 99 if (!m_shared) 100 return; 101 102 switch (m_mode) { 103 case SingleThreadVerificationMode: 104 ASSERT(shared != previouslyShared); 105 // Capture the current thread to verify that subsequent ref/deref happen on this thread. 106 m_owningThread = currentThread(); 107 return; 108 109 #if HAVE(DISPATCH_H) 110 case SingleDispatchQueueVerificationMode: 111 #endif 112 case MutexVerificationMode: 113 case NoVerificationMode: 114 return; 115 } 116 ASSERT_NOT_REACHED(); 117 } 118 119 // Is it OK to use the object at this moment on the current thread? 120 bool isSafeToUse() const 121 { 122 if (!m_shared) 123 return true; 124 125 switch (m_mode) { 126 case SingleThreadVerificationMode: 127 return m_owningThread == currentThread(); 128 129 case MutexVerificationMode: 130 if (!m_mutex->tryLock()) 131 return true; 132 m_mutex->unlock(); 133 return false; 134 135 #if HAVE(DISPATCH_H) 136 case SingleDispatchQueueVerificationMode: 137 return m_owningQueue == dispatch_get_current_queue(); 138 #endif 139 140 case NoVerificationMode: 141 return true; 142 } 143 ASSERT_NOT_REACHED(); 144 return true; 145 } 146 147 private: 148 enum VerificationMode { 149 SingleThreadVerificationMode, 150 MutexVerificationMode, 151 NoVerificationMode, 152 #if HAVE(DISPATCH_H) 153 SingleDispatchQueueVerificationMode, 154 #endif 155 }; 156 157 VerificationMode m_mode; 158 bool m_shared; 159 160 // Used by SingleThreadVerificationMode 161 ThreadIdentifier m_owningThread; 162 163 // Used by MutexVerificationMode. 164 Mutex* m_mutex; 165 166 #if HAVE(DISPATCH_H) 167 // Used by SingleDispatchQueueVerificationMode. 168 dispatch_queue_t m_owningQueue; 169 #endif 170 }; 171 172 } 173 174 #endif 175 #endif 176