summaryrefslogtreecommitdiff
path: root/src/include/atomic.h
blob: 0c22b269c7c198f2e521a1410bdcf5effdfb5bbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2011 New Dream Network
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 * @author Sage Weil <sage@newdream.net>
 */

#ifndef CEPH_ATOMIC_H
#define CEPH_ATOMIC_H

#ifdef __CEPH__
# include "acconfig.h"
#endif

#ifndef NO_ATOMIC_OPS

// libatomic_ops implementation
#include <atomic_ops.h>

// reinclude our assert to clobber the system one
#include "include/assert.h"

namespace ceph {
  class atomic_t {
    AO_t val;
  public:
    atomic_t(AO_t i=0) : val(i) {}
    void set(size_t v) {
      AO_store(&val, v);
    }
    AO_t inc() {
      return AO_fetch_and_add1(&val) + 1;
    }
    AO_t dec() {
      return AO_fetch_and_sub1_write(&val) - 1;
    }
    void add(AO_t add_me) {
      AO_fetch_and_add(&val, add_me);
    }
    void sub(int sub_me) {
      int negsub = 0 - sub_me;
      AO_fetch_and_add_write(&val, (AO_t)negsub);
    }
    AO_t read() const {
      // cast away const on the pointer.  this is only needed to build
      // on lenny, but not newer debians, so the atomic_ops.h got fixed
      // at some point.  this hack can go away someday...
      return AO_load_full((AO_t *)&val);
    }
  private:
    // forbid copying
    atomic_t(const atomic_t &other);
    atomic_t &operator=(const atomic_t &rhs);
  };
}
#else
/*
 * crappy slow implementation that uses a pthreads spinlock.
 */
#include <pthread.h>
#include "include/assert.h"

namespace ceph {
  class atomic_t {
    mutable pthread_spinlock_t lock;
    signed long val;
  public:
    atomic_t(int i=0)
      : val(i) {
      pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
    }
    ~atomic_t() {
      pthread_spin_destroy(&lock);
    }
    void set(size_t v) {
      pthread_spin_lock(&lock);
      val = v;
      pthread_spin_unlock(&lock);
    }
    int inc() {
      pthread_spin_lock(&lock);
      int r = ++val;
      pthread_spin_unlock(&lock);
      return r;
    }
    int dec() {
      pthread_spin_lock(&lock);
      int r = --val;
      pthread_spin_unlock(&lock);
      return r;
    }
    void add(int d) {
      pthread_spin_lock(&lock);
      val += d;
      pthread_spin_unlock(&lock);
    }
    void sub(int d) {
      pthread_spin_lock(&lock);
      val -= d;
      pthread_spin_unlock(&lock);
    }
    int read() const {
      signed long ret;
      pthread_spin_lock(&lock);
      ret = val;
      pthread_spin_unlock(&lock);
      return ret;
    }
  private:
    // forbid copying
    atomic_t(const atomic_t &other);
    atomic_t &operator=(const atomic_t &rhs);
  };
}
#endif
#endif