-
Notifications
You must be signed in to change notification settings - Fork 0
/
MultiThreadArray.h
162 lines (130 loc) · 4.18 KB
/
MultiThreadArray.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#ifndef FLAT_COMBINE_MULTITHREADARRAY_H
#define FLAT_COMBINE_MULTITHREADARRAY_H
#include <array>
#include <memory>
namespace Array {
template <typename Type, std::size_t SIZE>
class MultiThreadArraySlot;
template <typename Type, std::size_t SIZE>
class MultiThreadArray {
public:
using task_type = std::pair<MultiThreadArraySlot<Type, SIZE>*, int>;
/*
* Operation codes, this data stored in FlatCombine, and passed to shared structure
* and used in Execute() method
*/
enum Operation {
NOT_SET, // <==== always should be (!)
SET,
GET,
SET_TO_ZERO
};
/*
* Error codes, this data stored in MultiThreadArraySlot (int error_code), and user
* can check result of execution (is it OK or the error has happend)
*/
enum ErrorCode {
OK,
BAD_INDEX,
UNSUPPORTED_OPERATION
};
/*
* This is user's method of execution pack of task, could be implemented as user want
*/
template <std::size_t SHOT_N>
void Execute(std::array<task_type, SHOT_N> &tasks, size_t n) {
MultiThreadArraySlot<Type, SIZE> *slot;
int op_code;
for (size_t i = 0; i < n; i++) {
// Receive request info (slot and operation code)
std::tie(slot, op_code) = tasks[i];
// Set error_code to some value if error happend
int index = slot->index();
if (not check_index(index)) {
slot->error_code = ErrorCode::BAD_INDEX;
continue;
}
// Set error_code to OK if all good and to UNSUPPORTED_OPERATION
// if we don't know such operation code
switch (op_code) {
case Operation::SET:
_array[index] = slot->data();
slot->error_code = ErrorCode::OK;
break;
case Operation::GET:
slot->data(_array[index]);
slot->error_code = ErrorCode::OK;
break;
case Operation::SET_TO_ZERO:
_array[index] = 0;
slot->error_code = ErrorCode::OK;
break;
default: {
slot->error_code = ErrorCode::UNSUPPORTED_OPERATION;
break;
}
}
}
}
private:
bool check_index(int index) {
return 0 <= index && index < SIZE;
}
std::array<Type, SIZE> _array;
};
template <typename Type, std::size_t SIZE>
class MultiThreadArraySlot {
public:
using task_type = std::pair<MultiThreadArraySlot<Type, SIZE>*, int>;
/* These function need for flat combiner */
/**
* Called by flat combiner, pass pack of tasks
* @tparam SHOT_N - max tasks number
* @param tasks - pack of tasks
* @param n - tasks number
*/
template <std::size_t SHOT_N>
void execute(std::array<task_type, SHOT_N> &tasks, size_t n) {
_storage->Execute(tasks, n);
}
/* Called by flat combiner, during set of operation */
void prepare_data(int index) {
_index = index;
}
void prepare_data(int index, const Type &value) {
prepare_data(index);
_data = value;
}
/* Special field for store error_code after executing of operation */
int error_code;
/* Some functions not related to FlatCombine */
/* Get index in slot */
int index() const {
return _index;
}
/* Get data in slot */
Type &data() {
return _data;
}
/* Set some data to slot */
void data(Type &new_data) {
_data = new_data;
}
/*
* Note, that after do flat_combine->get_slot(), we received empty slot,
* so we want to initialize it.
*
* This could do FlatCombiner, but in this case it will overload different user data
* types and functions.
*/
void init(const std::shared_ptr<MultiThreadArray<Type, SIZE>> &storage) {
_storage = std::move(storage);
}
private:
/* Some user data for execute query */
std::shared_ptr<MultiThreadArray<Type, SIZE>> _storage;
Type _data;
int _index;
};
}; // namespace Array
#endif //FLAT_COMBINE_MULTITHREADARRAY_H