1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is a low level implementation of atomic semantics for reference
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// counting.  Please use base/memory/ref_counted.h directly instead.
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The implementation includes annotations to avoid some false positives
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// when using data race detection tools.
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef BASE_ATOMIC_REF_COUNT_H_
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BASE_ATOMIC_REF_COUNT_H_
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/atomicops.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef subtle::Atomic32 AtomicRefCount;
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Increment a reference count by "increment", which must exceed 0.
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline void AtomicRefCountIncN(volatile AtomicRefCount *ptr,
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               AtomicRefCount increment) {
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  subtle::NoBarrier_AtomicIncrement(ptr, increment);
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Decrement a reference count by "decrement", which must exceed 0,
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and return whether the result is non-zero.
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Insert barriers to ensure that state written before the reference count
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// became zero will be visible to a thread that has just made the count zero.
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr,
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               AtomicRefCount decrement) {
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ANNOTATE_HAPPENS_BEFORE(ptr);
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0);
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!res) {
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ANNOTATE_HAPPENS_AFTER(ptr);
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return res;
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Increment a reference count by 1.
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline void AtomicRefCountInc(volatile AtomicRefCount *ptr) {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::AtomicRefCountIncN(ptr, 1);
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Decrement a reference count by 1 and return whether the result is non-zero.
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Insert barriers to ensure that state written before the reference count
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// became zero will be visible to a thread that has just made the count zero.
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline bool AtomicRefCountDec(volatile AtomicRefCount *ptr) {
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return base::AtomicRefCountDecN(ptr, 1);
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Return whether the reference count is one.  If the reference count is used
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// in the conventional way, a refrerence count of 1 implies that the current
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// thread owns the reference and no other thread shares it.  This call performs
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the test for a reference count of one, and performs the memory barrier
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// needed for the owning thread to act on the object, knowing that it has
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// exclusive access to the object.
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) {
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool res = (subtle::Acquire_Load(ptr) == 1);
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (res) {
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ANNOTATE_HAPPENS_AFTER(ptr);
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return res;
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Return whether the reference count is zero.  With conventional object
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// referencing counting, the object will be destroyed, so the reference count
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// should never be zero.  Hence this is generally used for a debug check.
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) {
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool res = (subtle::Acquire_Load(ptr) == 0);
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (res) {
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ANNOTATE_HAPPENS_AFTER(ptr);
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return res;
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // BASE_ATOMIC_REF_COUNT_H_
82