| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 | 41 |
| 42 // Verifies that a class is used in a way that respects its lack of | 42 // Verifies that a class is used in a way that respects its lack of |
| 43 // thread-safety. The default mode is to verify that the object will only be | 43 // thread-safety. The default mode is to verify that the object will only be |
| 44 // used on a single thread. The thread gets captured when setShared(true) is | 44 // used on a single thread. The thread gets captured when setShared(true) is |
| 45 // called. The mode may be changed by calling useMutexMode (or | 45 // called. The mode may be changed by calling useMutexMode (or |
| 46 // turnOffVerification). | 46 // turnOffVerification). |
| 47 class ThreadRestrictionVerifier { | 47 class ThreadRestrictionVerifier { |
| 48 public: | 48 public: |
| 49 ThreadRestrictionVerifier() : m_shared(false), m_owningThread(0) {} | 49 ThreadRestrictionVerifier() : m_shared(false), m_owningThread(0) {} |
| 50 | 50 |
| 51 void checkSafeToUse() const { | 51 // Call onRef() before refCount is incremented in ref(). Returns whether the |
| 52 // If this assert fires, it either indicates a thread safety issue or | 52 // ref() is safe. |
| 53 // that the verification needs to change. | 53 template <typename COUNTERTYPE> |
| 54 SECURITY_DCHECK(isSafeToUse()); | 54 bool onRef(COUNTERTYPE refCount) { |
| 55 } | |
| 56 | |
| 57 // Call onRef() before refCount is incremented in ref(). | |
| 58 void onRef(int refCount) { | |
| 59 // Start thread verification as soon as the ref count gets to 2. This | 55 // Start thread verification as soon as the ref count gets to 2. This |
| 60 // heuristic reflects the fact that items are often created on one | 56 // heuristic reflects the fact that items are often created on one |
| 61 // thread and then given to another thread to be used. | 57 // thread and then given to another thread to be used. |
| 62 // FIXME: Make this restriction tigher. Especially as we move to more | 58 // FIXME: Make this restriction tigher. Especially as we move to more |
| 63 // common methods for sharing items across threads like | 59 // common methods for sharing items across threads like |
| 64 // CrossThreadCopier.h | 60 // CrossThreadCopier.h |
| 65 // We should be able to add a "detachFromThread" method to make this | 61 // We should be able to add a "detachFromThread" method to make this |
| 66 // explicit. | 62 // explicit. |
| 67 if (refCount == 1) | 63 if (refCount == 1) |
| 68 setShared(true); | 64 setShared(true); |
| 69 checkSafeToUse(); | 65 return isSafeToUse(); |
| 70 } | 66 } |
| 71 | 67 |
| 72 // Call onDeref() before refCount is decremented in deref(). | 68 // Call onDeref() before refCount is decremented in deref(). Returns whether |
| 73 void onDeref(int refCount) { | 69 // the deref() is safe. |
| 74 checkSafeToUse(); | 70 template <typename COUNTERTYPE> |
| 75 | 71 bool onDeref(COUNTERTYPE refCount) { |
| 72 bool safe = isSafeToUse(); |
| 76 // Stop thread verification when the ref goes to 1 because it | 73 // Stop thread verification when the ref goes to 1 because it |
| 77 // is safe to be passed to another thread at this point. | 74 // is safe to be passed to another thread at this point. |
| 78 if (refCount == 2) | 75 if (refCount == 2) |
| 79 setShared(false); | 76 setShared(false); |
| 77 return safe; |
| 78 } |
| 79 |
| 80 // Is it OK to use the object at this moment on the current thread? |
| 81 bool isSafeToUse() const { |
| 82 if (!m_shared) |
| 83 return true; |
| 84 |
| 85 DCHECK_GT(m_owningThread, 0); |
| 86 return m_owningThread == currentThread(); |
| 80 } | 87 } |
| 81 | 88 |
| 82 private: | 89 private: |
| 83 // Indicates that the object may (or may not) be owned by more than one place. | 90 // Indicates that the object may (or may not) be owned by more than one place. |
| 84 void setShared(bool shared) { | 91 void setShared(bool shared) { |
| 85 bool previouslyShared = m_shared; | 92 bool previouslyShared = m_shared; |
| 86 m_shared = shared; | 93 m_shared = shared; |
| 87 | 94 |
| 88 if (!m_shared) | 95 if (!m_shared) |
| 89 return; | 96 return; |
| 90 | 97 |
| 91 DCHECK_NE(shared, previouslyShared); | 98 DCHECK_NE(shared, previouslyShared); |
| 92 // Capture the current thread to verify that subsequent ref/deref happen on | 99 // Capture the current thread to verify that subsequent ref/deref happen on |
| 93 // this thread. | 100 // this thread. |
| 94 m_owningThread = currentThread(); | 101 m_owningThread = currentThread(); |
| 95 } | 102 } |
| 96 | 103 |
| 97 // Is it OK to use the object at this moment on the current thread? | |
| 98 bool isSafeToUse() const { | |
| 99 if (!m_shared) | |
| 100 return true; | |
| 101 | |
| 102 return m_owningThread == currentThread(); | |
| 103 } | |
| 104 | |
| 105 bool m_shared; | 104 bool m_shared; |
| 106 | 105 |
| 107 ThreadIdentifier m_owningThread; | 106 ThreadIdentifier m_owningThread; |
| 108 }; | 107 }; |
| 109 | 108 |
| 110 } // namespace WTF | 109 } // namespace WTF |
| 111 | 110 |
| 112 #endif // DCHECK_IS_ON() | 111 #endif // DCHECK_IS_ON() |
| 113 #endif // ThreadRestrictionVerifier_h | 112 #endif // ThreadRestrictionVerifier_h |
| OLD | NEW |