filiptepper-leveldb-ruby 0.14
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +24 -0
- data/README +72 -0
- data/ext/leveldb/extconf.rb +14 -0
- data/ext/leveldb/leveldb.cc +530 -0
- data/ext/leveldb/platform.rb +83 -0
- data/leveldb/Makefile +191 -0
- data/leveldb/build_detect_platform +160 -0
- data/leveldb/db/builder.cc +88 -0
- data/leveldb/db/builder.h +34 -0
- data/leveldb/db/c.cc +581 -0
- data/leveldb/db/corruption_test.cc +359 -0
- data/leveldb/db/db_bench.cc +970 -0
- data/leveldb/db/db_impl.cc +1448 -0
- data/leveldb/db/db_impl.h +194 -0
- data/leveldb/db/db_iter.cc +299 -0
- data/leveldb/db/db_iter.h +26 -0
- data/leveldb/db/db_test.cc +1901 -0
- data/leveldb/db/dbformat.cc +140 -0
- data/leveldb/db/dbformat.h +227 -0
- data/leveldb/db/dbformat_test.cc +112 -0
- data/leveldb/db/filename.cc +139 -0
- data/leveldb/db/filename.h +80 -0
- data/leveldb/db/filename_test.cc +122 -0
- data/leveldb/db/log_format.h +35 -0
- data/leveldb/db/log_reader.cc +259 -0
- data/leveldb/db/log_reader.h +108 -0
- data/leveldb/db/log_test.cc +500 -0
- data/leveldb/db/log_writer.cc +103 -0
- data/leveldb/db/log_writer.h +48 -0
- data/leveldb/db/memtable.cc +145 -0
- data/leveldb/db/memtable.h +91 -0
- data/leveldb/db/repair.cc +389 -0
- data/leveldb/db/skiplist.h +379 -0
- data/leveldb/db/skiplist_test.cc +378 -0
- data/leveldb/db/snapshot.h +66 -0
- data/leveldb/db/table_cache.cc +121 -0
- data/leveldb/db/table_cache.h +61 -0
- data/leveldb/db/version_edit.cc +266 -0
- data/leveldb/db/version_edit.h +107 -0
- data/leveldb/db/version_edit_test.cc +46 -0
- data/leveldb/db/version_set.cc +1402 -0
- data/leveldb/db/version_set.h +370 -0
- data/leveldb/db/version_set_test.cc +179 -0
- data/leveldb/db/write_batch.cc +147 -0
- data/leveldb/db/write_batch_internal.h +49 -0
- data/leveldb/db/write_batch_test.cc +120 -0
- data/leveldb/helpers/memenv/memenv.cc +374 -0
- data/leveldb/helpers/memenv/memenv.h +20 -0
- data/leveldb/helpers/memenv/memenv_test.cc +232 -0
- data/leveldb/include/leveldb/c.h +275 -0
- data/leveldb/include/leveldb/cache.h +99 -0
- data/leveldb/include/leveldb/comparator.h +63 -0
- data/leveldb/include/leveldb/db.h +161 -0
- data/leveldb/include/leveldb/env.h +323 -0
- data/leveldb/include/leveldb/filter_policy.h +70 -0
- data/leveldb/include/leveldb/iterator.h +100 -0
- data/leveldb/include/leveldb/options.h +195 -0
- data/leveldb/include/leveldb/slice.h +109 -0
- data/leveldb/include/leveldb/status.h +106 -0
- data/leveldb/include/leveldb/table.h +85 -0
- data/leveldb/include/leveldb/table_builder.h +92 -0
- data/leveldb/include/leveldb/write_batch.h +64 -0
- data/leveldb/port/atomic_pointer.h +144 -0
- data/leveldb/port/port.h +21 -0
- data/leveldb/port/port_android.cc +64 -0
- data/leveldb/port/port_android.h +159 -0
- data/leveldb/port/port_example.h +125 -0
- data/leveldb/port/port_posix.cc +50 -0
- data/leveldb/port/port_posix.h +129 -0
- data/leveldb/port/win/stdint.h +24 -0
- data/leveldb/table/block.cc +267 -0
- data/leveldb/table/block.h +44 -0
- data/leveldb/table/block_builder.cc +109 -0
- data/leveldb/table/block_builder.h +57 -0
- data/leveldb/table/filter_block.cc +111 -0
- data/leveldb/table/filter_block.h +68 -0
- data/leveldb/table/filter_block_test.cc +128 -0
- data/leveldb/table/format.cc +145 -0
- data/leveldb/table/format.h +108 -0
- data/leveldb/table/iterator.cc +67 -0
- data/leveldb/table/iterator_wrapper.h +63 -0
- data/leveldb/table/merger.cc +197 -0
- data/leveldb/table/merger.h +26 -0
- data/leveldb/table/table.cc +276 -0
- data/leveldb/table/table_builder.cc +270 -0
- data/leveldb/table/table_test.cc +838 -0
- data/leveldb/table/two_level_iterator.cc +182 -0
- data/leveldb/table/two_level_iterator.h +34 -0
- data/leveldb/util/arena.cc +68 -0
- data/leveldb/util/arena.h +68 -0
- data/leveldb/util/arena_test.cc +68 -0
- data/leveldb/util/bloom.cc +95 -0
- data/leveldb/util/bloom_test.cc +159 -0
- data/leveldb/util/cache.cc +328 -0
- data/leveldb/util/cache_test.cc +186 -0
- data/leveldb/util/coding.cc +194 -0
- data/leveldb/util/coding.h +104 -0
- data/leveldb/util/coding_test.cc +173 -0
- data/leveldb/util/comparator.cc +76 -0
- data/leveldb/util/crc32c.cc +332 -0
- data/leveldb/util/crc32c.h +45 -0
- data/leveldb/util/crc32c_test.cc +72 -0
- data/leveldb/util/env.cc +96 -0
- data/leveldb/util/env_posix.cc +609 -0
- data/leveldb/util/env_test.cc +104 -0
- data/leveldb/util/filter_policy.cc +11 -0
- data/leveldb/util/hash.cc +45 -0
- data/leveldb/util/hash.h +19 -0
- data/leveldb/util/histogram.cc +139 -0
- data/leveldb/util/histogram.h +42 -0
- data/leveldb/util/logging.cc +81 -0
- data/leveldb/util/logging.h +47 -0
- data/leveldb/util/mutexlock.h +39 -0
- data/leveldb/util/options.cc +29 -0
- data/leveldb/util/posix_logger.h +98 -0
- data/leveldb/util/random.h +59 -0
- data/leveldb/util/status.cc +75 -0
- data/leveldb/util/testharness.cc +77 -0
- data/leveldb/util/testharness.h +138 -0
- data/leveldb/util/testutil.cc +51 -0
- data/leveldb/util/testutil.h +53 -0
- data/lib/leveldb.rb +76 -0
- metadata +175 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
// Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors.
|
4
|
+
//
|
5
|
+
// A Status encapsulates the result of an operation. It may indicate success,
|
6
|
+
// or it may indicate an error with an associated error message.
|
7
|
+
//
|
8
|
+
// Multiple threads can invoke const methods on a Status without
|
9
|
+
// external synchronization, but if any of the threads may call a
|
10
|
+
// non-const method, all threads accessing the same Status must use
|
11
|
+
// external synchronization.
|
12
|
+
|
13
|
+
#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_
|
14
|
+
#define STORAGE_LEVELDB_INCLUDE_STATUS_H_
|
15
|
+
|
16
|
+
#include <string>
|
17
|
+
#include "leveldb/slice.h"
|
18
|
+
|
19
|
+
namespace leveldb {
|
20
|
+
|
21
|
+
class Status {
|
22
|
+
public:
|
23
|
+
// Create a success status.
|
24
|
+
Status() : state_(NULL) { }
|
25
|
+
~Status() { delete[] state_; }
|
26
|
+
|
27
|
+
// Copy the specified status.
|
28
|
+
Status(const Status& s);
|
29
|
+
void operator=(const Status& s);
|
30
|
+
|
31
|
+
// Return a success status.
|
32
|
+
static Status OK() { return Status(); }
|
33
|
+
|
34
|
+
// Return error status of an appropriate type.
|
35
|
+
static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) {
|
36
|
+
return Status(kNotFound, msg, msg2);
|
37
|
+
}
|
38
|
+
static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) {
|
39
|
+
return Status(kCorruption, msg, msg2);
|
40
|
+
}
|
41
|
+
static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) {
|
42
|
+
return Status(kNotSupported, msg, msg2);
|
43
|
+
}
|
44
|
+
static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) {
|
45
|
+
return Status(kInvalidArgument, msg, msg2);
|
46
|
+
}
|
47
|
+
static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) {
|
48
|
+
return Status(kIOError, msg, msg2);
|
49
|
+
}
|
50
|
+
|
51
|
+
// Returns true iff the status indicates success.
|
52
|
+
bool ok() const { return (state_ == NULL); }
|
53
|
+
|
54
|
+
// Returns true iff the status indicates a NotFound error.
|
55
|
+
bool IsNotFound() const { return code() == kNotFound; }
|
56
|
+
|
57
|
+
// Returns true iff the status indicates a Corruption error.
|
58
|
+
bool IsCorruption() const { return code() == kCorruption; }
|
59
|
+
|
60
|
+
// Returns true iff the status indicates an IOError.
|
61
|
+
bool IsIOError() const { return code() == kIOError; }
|
62
|
+
|
63
|
+
// Return a string representation of this status suitable for printing.
|
64
|
+
// Returns the string "OK" for success.
|
65
|
+
std::string ToString() const;
|
66
|
+
|
67
|
+
private:
|
68
|
+
// OK status has a NULL state_. Otherwise, state_ is a new[] array
|
69
|
+
// of the following form:
|
70
|
+
// state_[0..3] == length of message
|
71
|
+
// state_[4] == code
|
72
|
+
// state_[5..] == message
|
73
|
+
const char* state_;
|
74
|
+
|
75
|
+
enum Code {
|
76
|
+
kOk = 0,
|
77
|
+
kNotFound = 1,
|
78
|
+
kCorruption = 2,
|
79
|
+
kNotSupported = 3,
|
80
|
+
kInvalidArgument = 4,
|
81
|
+
kIOError = 5
|
82
|
+
};
|
83
|
+
|
84
|
+
Code code() const {
|
85
|
+
return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
|
86
|
+
}
|
87
|
+
|
88
|
+
Status(Code code, const Slice& msg, const Slice& msg2);
|
89
|
+
static const char* CopyState(const char* s);
|
90
|
+
};
|
91
|
+
|
92
|
+
inline Status::Status(const Status& s) {
|
93
|
+
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
|
94
|
+
}
|
95
|
+
inline void Status::operator=(const Status& s) {
|
96
|
+
// The following condition catches both aliasing (when this == &s),
|
97
|
+
// and the common case where both s and *this are ok.
|
98
|
+
if (state_ != s.state_) {
|
99
|
+
delete[] state_;
|
100
|
+
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
} // namespace leveldb
|
105
|
+
|
106
|
+
#endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_
|
@@ -0,0 +1,85 @@
|
|
1
|
+
// Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors.
|
4
|
+
|
5
|
+
#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_H_
|
6
|
+
#define STORAGE_LEVELDB_INCLUDE_TABLE_H_
|
7
|
+
|
8
|
+
#include <stdint.h>
|
9
|
+
#include "leveldb/iterator.h"
|
10
|
+
|
11
|
+
namespace leveldb {
|
12
|
+
|
13
|
+
class Block;
|
14
|
+
class BlockHandle;
|
15
|
+
class Footer;
|
16
|
+
struct Options;
|
17
|
+
class RandomAccessFile;
|
18
|
+
struct ReadOptions;
|
19
|
+
class TableCache;
|
20
|
+
|
21
|
+
// A Table is a sorted map from strings to strings. Tables are
|
22
|
+
// immutable and persistent. A Table may be safely accessed from
|
23
|
+
// multiple threads without external synchronization.
|
24
|
+
class Table {
|
25
|
+
public:
|
26
|
+
// Attempt to open the table that is stored in bytes [0..file_size)
|
27
|
+
// of "file", and read the metadata entries necessary to allow
|
28
|
+
// retrieving data from the table.
|
29
|
+
//
|
30
|
+
// If successful, returns ok and sets "*table" to the newly opened
|
31
|
+
// table. The client should delete "*table" when no longer needed.
|
32
|
+
// If there was an error while initializing the table, sets "*table"
|
33
|
+
// to NULL and returns a non-ok status. Does not take ownership of
|
34
|
+
// "*source", but the client must ensure that "source" remains live
|
35
|
+
// for the duration of the returned table's lifetime.
|
36
|
+
//
|
37
|
+
// *file must remain live while this Table is in use.
|
38
|
+
static Status Open(const Options& options,
|
39
|
+
RandomAccessFile* file,
|
40
|
+
uint64_t file_size,
|
41
|
+
Table** table);
|
42
|
+
|
43
|
+
~Table();
|
44
|
+
|
45
|
+
// Returns a new iterator over the table contents.
|
46
|
+
// The result of NewIterator() is initially invalid (caller must
|
47
|
+
// call one of the Seek methods on the iterator before using it).
|
48
|
+
Iterator* NewIterator(const ReadOptions&) const;
|
49
|
+
|
50
|
+
// Given a key, return an approximate byte offset in the file where
|
51
|
+
// the data for that key begins (or would begin if the key were
|
52
|
+
// present in the file). The returned value is in terms of file
|
53
|
+
// bytes, and so includes effects like compression of the underlying data.
|
54
|
+
// E.g., the approximate offset of the last key in the table will
|
55
|
+
// be close to the file length.
|
56
|
+
uint64_t ApproximateOffsetOf(const Slice& key) const;
|
57
|
+
|
58
|
+
private:
|
59
|
+
struct Rep;
|
60
|
+
Rep* rep_;
|
61
|
+
|
62
|
+
explicit Table(Rep* rep) { rep_ = rep; }
|
63
|
+
static Iterator* BlockReader(void*, const ReadOptions&, const Slice&);
|
64
|
+
|
65
|
+
// Calls (*handle_result)(arg, ...) with the entry found after a call
|
66
|
+
// to Seek(key). May not make such a call if filter policy says
|
67
|
+
// that key is not present.
|
68
|
+
friend class TableCache;
|
69
|
+
Status InternalGet(
|
70
|
+
const ReadOptions&, const Slice& key,
|
71
|
+
void* arg,
|
72
|
+
void (*handle_result)(void* arg, const Slice& k, const Slice& v));
|
73
|
+
|
74
|
+
|
75
|
+
void ReadMeta(const Footer& footer);
|
76
|
+
void ReadFilter(const Slice& filter_handle_value);
|
77
|
+
|
78
|
+
// No copying allowed
|
79
|
+
Table(const Table&);
|
80
|
+
void operator=(const Table&);
|
81
|
+
};
|
82
|
+
|
83
|
+
} // namespace leveldb
|
84
|
+
|
85
|
+
#endif // STORAGE_LEVELDB_INCLUDE_TABLE_H_
|
@@ -0,0 +1,92 @@
|
|
1
|
+
// Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors.
|
4
|
+
//
|
5
|
+
// TableBuilder provides the interface used to build a Table
|
6
|
+
// (an immutable and sorted map from keys to values).
|
7
|
+
//
|
8
|
+
// Multiple threads can invoke const methods on a TableBuilder without
|
9
|
+
// external synchronization, but if any of the threads may call a
|
10
|
+
// non-const method, all threads accessing the same TableBuilder must use
|
11
|
+
// external synchronization.
|
12
|
+
|
13
|
+
#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_
|
14
|
+
#define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_
|
15
|
+
|
16
|
+
#include <stdint.h>
|
17
|
+
#include "leveldb/options.h"
|
18
|
+
#include "leveldb/status.h"
|
19
|
+
|
20
|
+
namespace leveldb {
|
21
|
+
|
22
|
+
class BlockBuilder;
|
23
|
+
class BlockHandle;
|
24
|
+
class WritableFile;
|
25
|
+
|
26
|
+
class TableBuilder {
|
27
|
+
public:
|
28
|
+
// Create a builder that will store the contents of the table it is
|
29
|
+
// building in *file. Does not close the file. It is up to the
|
30
|
+
// caller to close the file after calling Finish().
|
31
|
+
TableBuilder(const Options& options, WritableFile* file);
|
32
|
+
|
33
|
+
// REQUIRES: Either Finish() or Abandon() has been called.
|
34
|
+
~TableBuilder();
|
35
|
+
|
36
|
+
// Change the options used by this builder. Note: only some of the
|
37
|
+
// option fields can be changed after construction. If a field is
|
38
|
+
// not allowed to change dynamically and its value in the structure
|
39
|
+
// passed to the constructor is different from its value in the
|
40
|
+
// structure passed to this method, this method will return an error
|
41
|
+
// without changing any fields.
|
42
|
+
Status ChangeOptions(const Options& options);
|
43
|
+
|
44
|
+
// Add key,value to the table being constructed.
|
45
|
+
// REQUIRES: key is after any previously added key according to comparator.
|
46
|
+
// REQUIRES: Finish(), Abandon() have not been called
|
47
|
+
void Add(const Slice& key, const Slice& value);
|
48
|
+
|
49
|
+
// Advanced operation: flush any buffered key/value pairs to file.
|
50
|
+
// Can be used to ensure that two adjacent entries never live in
|
51
|
+
// the same data block. Most clients should not need to use this method.
|
52
|
+
// REQUIRES: Finish(), Abandon() have not been called
|
53
|
+
void Flush();
|
54
|
+
|
55
|
+
// Return non-ok iff some error has been detected.
|
56
|
+
Status status() const;
|
57
|
+
|
58
|
+
// Finish building the table. Stops using the file passed to the
|
59
|
+
// constructor after this function returns.
|
60
|
+
// REQUIRES: Finish(), Abandon() have not been called
|
61
|
+
Status Finish();
|
62
|
+
|
63
|
+
// Indicate that the contents of this builder should be abandoned. Stops
|
64
|
+
// using the file passed to the constructor after this function returns.
|
65
|
+
// If the caller is not going to call Finish(), it must call Abandon()
|
66
|
+
// before destroying this builder.
|
67
|
+
// REQUIRES: Finish(), Abandon() have not been called
|
68
|
+
void Abandon();
|
69
|
+
|
70
|
+
// Number of calls to Add() so far.
|
71
|
+
uint64_t NumEntries() const;
|
72
|
+
|
73
|
+
// Size of the file generated so far. If invoked after a successful
|
74
|
+
// Finish() call, returns the size of the final generated file.
|
75
|
+
uint64_t FileSize() const;
|
76
|
+
|
77
|
+
private:
|
78
|
+
bool ok() const { return status().ok(); }
|
79
|
+
void WriteBlock(BlockBuilder* block, BlockHandle* handle);
|
80
|
+
void WriteRawBlock(const Slice& data, CompressionType, BlockHandle* handle);
|
81
|
+
|
82
|
+
struct Rep;
|
83
|
+
Rep* rep_;
|
84
|
+
|
85
|
+
// No copying allowed
|
86
|
+
TableBuilder(const TableBuilder&);
|
87
|
+
void operator=(const TableBuilder&);
|
88
|
+
};
|
89
|
+
|
90
|
+
} // namespace leveldb
|
91
|
+
|
92
|
+
#endif // STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_
|
@@ -0,0 +1,64 @@
|
|
1
|
+
// Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors.
|
4
|
+
//
|
5
|
+
// WriteBatch holds a collection of updates to apply atomically to a DB.
|
6
|
+
//
|
7
|
+
// The updates are applied in the order in which they are added
|
8
|
+
// to the WriteBatch. For example, the value of "key" will be "v3"
|
9
|
+
// after the following batch is written:
|
10
|
+
//
|
11
|
+
// batch.Put("key", "v1");
|
12
|
+
// batch.Delete("key");
|
13
|
+
// batch.Put("key", "v2");
|
14
|
+
// batch.Put("key", "v3");
|
15
|
+
//
|
16
|
+
// Multiple threads can invoke const methods on a WriteBatch without
|
17
|
+
// external synchronization, but if any of the threads may call a
|
18
|
+
// non-const method, all threads accessing the same WriteBatch must use
|
19
|
+
// external synchronization.
|
20
|
+
|
21
|
+
#ifndef STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_
|
22
|
+
#define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_
|
23
|
+
|
24
|
+
#include <string>
|
25
|
+
#include "leveldb/status.h"
|
26
|
+
|
27
|
+
namespace leveldb {
|
28
|
+
|
29
|
+
class Slice;
|
30
|
+
|
31
|
+
class WriteBatch {
|
32
|
+
public:
|
33
|
+
WriteBatch();
|
34
|
+
~WriteBatch();
|
35
|
+
|
36
|
+
// Store the mapping "key->value" in the database.
|
37
|
+
void Put(const Slice& key, const Slice& value);
|
38
|
+
|
39
|
+
// If the database contains a mapping for "key", erase it. Else do nothing.
|
40
|
+
void Delete(const Slice& key);
|
41
|
+
|
42
|
+
// Clear all updates buffered in this batch.
|
43
|
+
void Clear();
|
44
|
+
|
45
|
+
// Support for iterating over the contents of a batch.
|
46
|
+
class Handler {
|
47
|
+
public:
|
48
|
+
virtual ~Handler();
|
49
|
+
virtual void Put(const Slice& key, const Slice& value) = 0;
|
50
|
+
virtual void Delete(const Slice& key) = 0;
|
51
|
+
};
|
52
|
+
Status Iterate(Handler* handler) const;
|
53
|
+
|
54
|
+
private:
|
55
|
+
friend class WriteBatchInternal;
|
56
|
+
|
57
|
+
std::string rep_; // See comment in write_batch.cc for the format of rep_
|
58
|
+
|
59
|
+
// Intentionally copyable
|
60
|
+
};
|
61
|
+
|
62
|
+
} // namespace leveldb
|
63
|
+
|
64
|
+
#endif // STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_
|
@@ -0,0 +1,144 @@
|
|
1
|
+
// Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors.
|
4
|
+
|
5
|
+
// AtomicPointer provides storage for a lock-free pointer.
|
6
|
+
// Platform-dependent implementation of AtomicPointer:
|
7
|
+
// - If the platform provides a cheap barrier, we use it with raw pointers
|
8
|
+
// - If cstdatomic is present (on newer versions of gcc, it is), we use
|
9
|
+
// a cstdatomic-based AtomicPointer. However we prefer the memory
|
10
|
+
// barrier based version, because at least on a gcc 4.4 32-bit build
|
11
|
+
// on linux, we have encountered a buggy <cstdatomic>
|
12
|
+
// implementation. Also, some <cstdatomic> implementations are much
|
13
|
+
// slower than a memory-barrier based implementation (~16ns for
|
14
|
+
// <cstdatomic> based acquire-load vs. ~1ns for a barrier based
|
15
|
+
// acquire-load).
|
16
|
+
// This code is based on atomicops-internals-* in Google's perftools:
|
17
|
+
// http://code.google.com/p/google-perftools/source/browse/#svn%2Ftrunk%2Fsrc%2Fbase
|
18
|
+
|
19
|
+
#ifndef PORT_ATOMIC_POINTER_H_
|
20
|
+
#define PORT_ATOMIC_POINTER_H_
|
21
|
+
|
22
|
+
#include <stdint.h>
|
23
|
+
#ifdef LEVELDB_CSTDATOMIC_PRESENT
|
24
|
+
#include <cstdatomic>
|
25
|
+
#endif
|
26
|
+
#ifdef OS_WIN
|
27
|
+
#include <windows.h>
|
28
|
+
#endif
|
29
|
+
#ifdef OS_MACOSX
|
30
|
+
#include <libkern/OSAtomic.h>
|
31
|
+
#endif
|
32
|
+
|
33
|
+
#if defined(_M_X64) || defined(__x86_64__)
|
34
|
+
#define ARCH_CPU_X86_FAMILY 1
|
35
|
+
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
|
36
|
+
#define ARCH_CPU_X86_FAMILY 1
|
37
|
+
#elif defined(__ARMEL__)
|
38
|
+
#define ARCH_CPU_ARM_FAMILY 1
|
39
|
+
#endif
|
40
|
+
|
41
|
+
namespace leveldb {
|
42
|
+
namespace port {
|
43
|
+
|
44
|
+
// Define MemoryBarrier() if available
|
45
|
+
// Windows on x86
|
46
|
+
#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
|
47
|
+
// windows.h already provides a MemoryBarrier(void) macro
|
48
|
+
// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx
|
49
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
50
|
+
|
51
|
+
// Gcc on x86
|
52
|
+
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__)
|
53
|
+
inline void MemoryBarrier() {
|
54
|
+
// See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
|
55
|
+
// this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
|
56
|
+
__asm__ __volatile__("" : : : "memory");
|
57
|
+
}
|
58
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
59
|
+
|
60
|
+
// Sun Studio
|
61
|
+
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__SUNPRO_CC)
|
62
|
+
inline void MemoryBarrier() {
|
63
|
+
// See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
|
64
|
+
// this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
|
65
|
+
asm volatile("" : : : "memory");
|
66
|
+
}
|
67
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
68
|
+
|
69
|
+
// Mac OS
|
70
|
+
#elif defined(OS_MACOSX)
|
71
|
+
inline void MemoryBarrier() {
|
72
|
+
OSMemoryBarrier();
|
73
|
+
}
|
74
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
75
|
+
|
76
|
+
// ARM
|
77
|
+
#elif defined(ARCH_CPU_ARM_FAMILY)
|
78
|
+
typedef void (*LinuxKernelMemoryBarrierFunc)(void);
|
79
|
+
LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
|
80
|
+
(LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
|
81
|
+
inline void MemoryBarrier() {
|
82
|
+
pLinuxKernelMemoryBarrier();
|
83
|
+
}
|
84
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
85
|
+
|
86
|
+
#endif
|
87
|
+
|
88
|
+
// AtomicPointer built using platform-specific MemoryBarrier()
|
89
|
+
#if defined(LEVELDB_HAVE_MEMORY_BARRIER)
|
90
|
+
class AtomicPointer {
|
91
|
+
private:
|
92
|
+
void* rep_;
|
93
|
+
public:
|
94
|
+
AtomicPointer() { }
|
95
|
+
explicit AtomicPointer(void* p) : rep_(p) {}
|
96
|
+
inline void* NoBarrier_Load() const { return rep_; }
|
97
|
+
inline void NoBarrier_Store(void* v) { rep_ = v; }
|
98
|
+
inline void* Acquire_Load() const {
|
99
|
+
void* result = rep_;
|
100
|
+
MemoryBarrier();
|
101
|
+
return result;
|
102
|
+
}
|
103
|
+
inline void Release_Store(void* v) {
|
104
|
+
MemoryBarrier();
|
105
|
+
rep_ = v;
|
106
|
+
}
|
107
|
+
};
|
108
|
+
|
109
|
+
// AtomicPointer based on <cstdatomic>
|
110
|
+
#elif defined(LEVELDB_CSTDATOMIC_PRESENT)
|
111
|
+
class AtomicPointer {
|
112
|
+
private:
|
113
|
+
std::atomic<void*> rep_;
|
114
|
+
public:
|
115
|
+
AtomicPointer() { }
|
116
|
+
explicit AtomicPointer(void* v) : rep_(v) { }
|
117
|
+
inline void* Acquire_Load() const {
|
118
|
+
return rep_.load(std::memory_order_acquire);
|
119
|
+
}
|
120
|
+
inline void Release_Store(void* v) {
|
121
|
+
rep_.store(v, std::memory_order_release);
|
122
|
+
}
|
123
|
+
inline void* NoBarrier_Load() const {
|
124
|
+
return rep_.load(std::memory_order_relaxed);
|
125
|
+
}
|
126
|
+
inline void NoBarrier_Store(void* v) {
|
127
|
+
rep_.store(v, std::memory_order_relaxed);
|
128
|
+
}
|
129
|
+
};
|
130
|
+
|
131
|
+
// We have neither MemoryBarrier(), nor <cstdatomic>
|
132
|
+
#else
|
133
|
+
#error Please implement AtomicPointer for this platform.
|
134
|
+
|
135
|
+
#endif
|
136
|
+
|
137
|
+
#undef LEVELDB_HAVE_MEMORY_BARRIER
|
138
|
+
#undef ARCH_CPU_X86_FAMILY
|
139
|
+
#undef ARCH_CPU_ARM_FAMILY
|
140
|
+
|
141
|
+
} // namespace port
|
142
|
+
} // namespace leveldb
|
143
|
+
|
144
|
+
#endif // PORT_ATOMIC_POINTER_H_
|