forked from voutcn/megahit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
atomic_bit_vector.h
111 lines (96 loc) · 3.32 KB
/
atomic_bit_vector.h
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
/*
* atomic_bit_vector.h
* This file is a part of MEGAHIT
*
* Copyright (C) 2014 The University of Hong Kong
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ATOMIC_BIT_VECTOR_H_
#define ATOMIC_BIT_VECTOR_H_
#include <assert.h>
#include <stdlib.h>
#include <memory.h>
#include <stdint.h>
#include <algorithm>
#include "mem_file_checker-inl.h"
class AtomicBitVector {
public:
typedef uint8_t word_t;
AtomicBitVector(size_t size = 0): size_(size) {
num_words_ = ((size + kBitsPerWord - 1) / kBitsPerWord);
capacity_ = num_words_;
if (num_words_ != 0) {
data_ = (word_t*) MallocAndCheck(sizeof(word_t) * num_words_, __FILE__, __LINE__);
assert(data_ != NULL);
memset(data_, 0, sizeof(word_t) * num_words_);
} else {
data_ = NULL;
}
}
~AtomicBitVector() {
if (data_ != NULL) { free(data_); }
}
size_t size() { return size_; }
bool get(size_t i) {
return bool((data_[i / kBitsPerWord] >> i % kBitsPerWord) & 1);
}
bool lock(size_t i) {
while (!((data_[i / kBitsPerWord] >> i % kBitsPerWord) & 1)) {
word_t old_value = data_[i / kBitsPerWord];
word_t new_value = data_[i / kBitsPerWord] | (word_t(1) << (i % kBitsPerWord));
if (__sync_bool_compare_and_swap(data_ + i / kBitsPerWord, old_value, new_value)) { return true; }
}
return false;
}
void set(size_t i) {
__sync_fetch_and_or(data_ + i / kBitsPerWord, word_t(1) << (i % kBitsPerWord));
}
void unset(size_t i) {
word_t mask = ~(word_t(1) << (i % kBitsPerWord));
__sync_fetch_and_and(data_ + i / kBitsPerWord, mask);
}
void reset(size_t size = 0) {
size_ = size;
num_words_ = (size + kBitsPerWord - 1) / kBitsPerWord;
if (capacity_ < num_words_) {
word_t *new_data = (word_t*) MallocAndCheck(sizeof(word_t) * num_words_, __FILE__, __LINE__);
assert(new_data != NULL);
if (data_ != NULL) {
free(data_);
}
data_ = new_data;
capacity_ = num_words_;
}
if (num_words_ != 0) {
memset(data_, 0, sizeof(word_t) * num_words_);
}
}
void swap(AtomicBitVector &rhs) {
if (data_ != rhs.data_) {
std::swap(data_, rhs.data_);
std::swap(size_, rhs.size_);
std::swap(num_words_, rhs.num_words_);
std::swap(capacity_, rhs.capacity_);
}
}
private:
static const int kBitsPerByte = 8;
static const int kBitsPerWord = sizeof(word_t) * kBitsPerByte;
size_t size_;
size_t num_words_;
size_t capacity_;
word_t *data_;
};
#endif