benchmark silo added
[c11concurrency-benchmarks.git] / silo / masstree / value_array.hh
1 /* Masstree
2  * Eddie Kohler, Yandong Mao, Robert Morris
3  * Copyright (c) 2012-2014 President and Fellows of Harvard College
4  * Copyright (c) 2012-2014 Massachusetts Institute of Technology
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, subject to the conditions
9  * listed in the Masstree LICENSE file. These conditions include: you must
10  * preserve this copyright notice, and you cannot mention the copyright
11  * holders in advertising related to the Software without their permission.
12  * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
13  * notice is a summary of the Masstree LICENSE file; the license in that file
14  * is legally binding.
15  */
16 #ifndef VALUE_ARRAY_HH
17 #define VALUE_ARRAY_HH
18 #include "compiler.hh"
19 #include "json.hh"
20
21 class value_array {
22   public:
23     typedef short index_type;
24     static const char *name() { return "Array"; }
25
26     typedef lcdf::Json Json;
27
28     inline value_array();
29
30     inline kvtimestamp_t timestamp() const;
31     inline int ncol() const;
32     inline Str col(int i) const;
33
34     void deallocate(threadinfo &ti);
35     void deallocate_rcu(threadinfo &ti);
36
37     value_array* update(const Json* first, const Json* last, kvtimestamp_t ts, threadinfo& ti) const;
38     static value_array* create(const Json* first, const Json* last, kvtimestamp_t ts, threadinfo& ti);
39     static inline value_array* create1(Str value, kvtimestamp_t ts, threadinfo& ti);
40     void deallocate_rcu_after_update(const Json* first, const Json* last, threadinfo& ti);
41     void deallocate_after_failed_update(const Json* first, const Json* last, threadinfo& ti);
42
43     template <typename PARSER>
44     static value_array* checkpoint_read(PARSER& par, kvtimestamp_t ts,
45                                         threadinfo& ti);
46     template <typename UNPARSER>
47     void checkpoint_write(UNPARSER& unpar) const;
48
49     void print(FILE* f, const char* prefix, int indent, Str key,
50                kvtimestamp_t initial_ts, const char* suffix = "") {
51         kvtimestamp_t adj_ts = timestamp_sub(ts_, initial_ts);
52         fprintf(f, "%s%*s%.*s = ### @" PRIKVTSPARTS "%s\n", prefix, indent, "",
53                 key.len, key.s, KVTS_HIGHPART(adj_ts), KVTS_LOWPART(adj_ts), suffix);
54     }
55
56     static inline lcdf::inline_string* make_column(Str str, threadinfo& ti);
57     static void deallocate_column(lcdf::inline_string* col, threadinfo& ti);
58     static void deallocate_column_rcu(lcdf::inline_string* col, threadinfo& ti);
59
60   private:
61     kvtimestamp_t ts_;
62     short ncol_;
63     lcdf::inline_string* cols_[0];
64
65     static inline size_t shallow_size(int ncol);
66     inline size_t shallow_size() const;
67     static value_array* make_sized_row(int ncol, kvtimestamp_t ts, threadinfo& ti);
68 };
69
70 inline value_array::value_array()
71     : ts_(0), ncol_(0) {
72 }
73
74 inline kvtimestamp_t value_array::timestamp() const {
75     return ts_;
76 }
77
78 inline int value_array::ncol() const {
79     return ncol_;
80 }
81
82 inline Str value_array::col(int i) const {
83     if (unsigned(i) < unsigned(ncol_) && cols_[i])
84         return Str(cols_[i]->s, cols_[i]->len);
85     else
86         return Str();
87 }
88
89 inline size_t value_array::shallow_size(int ncol) {
90     return sizeof(value_array) + sizeof(lcdf::inline_string*) * ncol;
91 }
92
93 inline size_t value_array::shallow_size() const {
94     return shallow_size(ncol_);
95 }
96
97 inline lcdf::inline_string* value_array::make_column(Str str, threadinfo& ti) {
98     using lcdf::inline_string;
99     if (str) {
100         inline_string* col = (inline_string*) ti.allocate(inline_string::size(str.length()), memtag_value);
101         col->len = str.length();
102         memcpy(col->s, str.data(), str.length());
103         return col;
104     } else
105         return 0;
106 }
107
108 inline void value_array::deallocate_column(lcdf::inline_string* col,
109                                            threadinfo& ti) {
110     if (col)
111         ti.deallocate(col, col->size(), memtag_value);
112 }
113
114 inline void value_array::deallocate_column_rcu(lcdf::inline_string* col,
115                                                threadinfo& ti) {
116     if (col)
117         ti.deallocate_rcu(col, col->size(), memtag_value);
118 }
119
120 inline value_array* value_array::create(const Json* first, const Json* last,
121                                         kvtimestamp_t ts, threadinfo& ti) {
122     value_array empty;
123     return empty.update(first, last, ts, ti);
124 }
125
126 inline value_array* value_array::create1(Str value, kvtimestamp_t ts, threadinfo& ti) {
127     value_array* row = (value_array*) ti.allocate(shallow_size(1), memtag_value);
128     row->ts_ = ts;
129     row->ncol_ = 1;
130     row->cols_[0] = make_column(value, ti);
131     return row;
132 }
133
134 template <typename PARSER>
135 value_array* value_array::checkpoint_read(PARSER& par, kvtimestamp_t ts,
136                                           threadinfo& ti) {
137     unsigned ncol;
138     par.read_array_header(ncol);
139     value_array* row = make_sized_row(ncol, ts, ti);
140     Str col;
141     for (unsigned i = 0; i != ncol; i++) {
142         par >> col;
143         if (col)
144             row->cols_[i] = make_column(col, ti);
145     }
146     return row;
147 }
148
149 template <typename UNPARSER>
150 void value_array::checkpoint_write(UNPARSER& unpar) const {
151     unpar.write_array_header(ncol_);
152     for (short i = 0; i != ncol_; i++)
153         unpar << col(i);
154 }
155
156 #endif