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 return !m_shared || m_owningThread == currentThread(); |
80 } | 83 } |
81 | 84 |
82 private: | 85 private: |
83 // Indicates that the object may (or may not) be owned by more than one place. | 86 // Indicates that the object may (or may not) be owned by more than one place. |
84 void setShared(bool shared) { | 87 void setShared(bool shared) { |
85 bool previouslyShared = m_shared; | 88 bool previouslyShared = m_shared; |
86 m_shared = shared; | 89 m_shared = shared; |
87 | 90 |
88 if (!m_shared) | 91 if (!m_shared) |
89 return; | 92 return; |
90 | 93 |
91 DCHECK_NE(shared, previouslyShared); | 94 DCHECK_NE(shared, previouslyShared); |
92 // Capture the current thread to verify that subsequent ref/deref happen on | 95 // Capture the current thread to verify that subsequent ref/deref happen on |
93 // this thread. | 96 // this thread. |
94 m_owningThread = currentThread(); | 97 m_owningThread = currentThread(); |
95 } | 98 } |
96 | 99 |
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; | 100 bool m_shared; |
106 | 101 |
107 ThreadIdentifier m_owningThread; | 102 ThreadIdentifier m_owningThread; |
108 }; | 103 }; |
109 | 104 |
110 } // namespace WTF | 105 } // namespace WTF |
111 | 106 |
112 #endif // DCHECK_IS_ON() | 107 #endif // DCHECK_IS_ON() |
113 #endif // ThreadRestrictionVerifier_h | 108 #endif // ThreadRestrictionVerifier_h |
OLD | NEW |