thread_collision_warner.cc 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // Copyright (c) 2010 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/threading/thread_collision_warner.h"
  5. #include <ostream>
  6. #include "base/notreached.h"
  7. #include "base/threading/platform_thread.h"
  8. namespace base {
  9. void DCheckAsserter::warn() {
  10. NOTREACHED() << "Thread Collision";
  11. }
  12. static subtle::Atomic32 CurrentThread() {
  13. const PlatformThreadId current_thread_id = PlatformThread::CurrentId();
  14. // We need to get the thread id into an atomic data type. This might be a
  15. // truncating conversion, but any loss-of-information just increases the
  16. // chance of a fault negative, not a false positive.
  17. const subtle::Atomic32 atomic_thread_id =
  18. static_cast<subtle::Atomic32>(current_thread_id);
  19. return atomic_thread_id;
  20. }
  21. void ThreadCollisionWarner::EnterSelf() {
  22. // If the active thread is 0 then I'll write the current thread ID
  23. // if two or more threads arrive here only one will succeed to
  24. // write on valid_thread_id_ the current thread ID.
  25. subtle::Atomic32 current_thread_id = CurrentThread();
  26. int previous_value = subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
  27. 0,
  28. current_thread_id);
  29. if (previous_value != 0 && previous_value != current_thread_id) {
  30. // gotcha! a thread is trying to use the same class and that is
  31. // not current thread.
  32. asserter_->warn();
  33. }
  34. subtle::NoBarrier_AtomicIncrement(&counter_, 1);
  35. }
  36. void ThreadCollisionWarner::Enter() {
  37. subtle::Atomic32 current_thread_id = CurrentThread();
  38. if (subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
  39. 0,
  40. current_thread_id) != 0) {
  41. // gotcha! another thread is trying to use the same class.
  42. asserter_->warn();
  43. }
  44. subtle::NoBarrier_AtomicIncrement(&counter_, 1);
  45. }
  46. void ThreadCollisionWarner::Leave() {
  47. if (subtle::Barrier_AtomicIncrement(&counter_, -1) == 0) {
  48. subtle::NoBarrier_Store(&valid_thread_id_, 0);
  49. }
  50. }
  51. } // namespace base