Jackalope / jlib (public) (License: GPLv3 or later) (since 2019-11-18) (hash sha1)
jlib C++ template library
Used to replace std functionality without exception handling.
- data structures
- filesystem routines
- crossplatform threads interface (currently only pthreads implementation)
- thread pool
- crossplatform dynamic memory functions interface (allocate, reallocate, deallocate) with alignment support
- high percision timer routines based on timespec
List of commits:
Subject Hash Author Date (UTC)
io_agent_mem.h identation changed from 4 to 3 d26588b1a1f71a0b98c17cf620b0bb1542a47d11 Your Name 2019-11-28 03:34:33
pass by pointer while inserting f8259daaa4477e7e5a568b15c23e6f717ce13f42 Your Name 2019-11-27 21:49:42
simplified convertions implementation 5dbd1b6cd3a06b87922a0778bc223693b547ea97 jp.larry 2019-11-27 05:56:37
take ref 739086550cb4ef85d10e083110253ee48820b47b jp.larry 2019-11-27 05:55:55
bug fix f150d538a332788ec41635e37f1d89e41e2d73f3 jp.larry 2019-11-27 05:55:11
more bugs solved d8d2fb72dfd2a3718ff6f26e68d64f5c7d02a348 Your Name 2019-11-27 04:29:04
replaced built_move, built_const and init_move with constructors, for emulating initializer-lists bd60c52d8e0d475dd69f11a48c05224507cfae0e Your Name 2019-11-27 03:42:54
make free deprecated a68c1b809ddc5c2a0018142a8435c67b8e4e0cf6 Your Name 2019-11-26 22:13:26
new template data structure jl::array as static c-array wrapper 68ff5a4049985d4ed013d0976b32e0613bb11ff0 jp.larry 2019-11-25 20:16:39
jassert release macro was wrong 97964f5cf3485502675b77b4df5b322921355cf7 jp.larry 2019-11-25 20:15:13
darray insert functions without checking for resize 0a168f4fc057f697bec6ad1f90faaaa7977c9537 Your Name 2019-11-25 08:39:45
replaced free with jl::deallocate 1d25f7cfe0a36ce04eeb8a6a08dc9f9eefe5c2df Your Name 2019-11-25 07:28:42
jabort_release and jassert_release macros 71349de13d880a9a13eb7cca9c46d460c30705b2 Your Name 2019-11-25 07:00:50
endianness convertion function fbff0fbb13891f7ad2975e226476cf0b56eabb36 Your Name 2019-11-25 06:06:17
overwise -> otherwise 89d07c9f30aba52e50526b0ecf1ed6eddb791764 Your Name 2019-11-25 06:01:13
init function was incorrect 6c820a36720b41b2efbfcf101bd12eb43f69a91d Your Name 2019-11-25 05:59:05
time struct for time measurements d6e362c72596c97abbd7c6f87c25eca1d3127c46 Your Name 2019-11-25 05:58:50
jassert macro, assert alternative e5b46d371c19ec6608c861c8b93a9963f117ec6d Your Name 2019-11-25 05:43:03
typo 14b869ada95c37bcc75a549cdcedae1b0b2ba76d Your Name 2019-11-25 03:27:12
thread pool cleanup 0b783f47cd02fb118f299784b52209e259646b25 Your Name 2019-11-25 03:23:02
Commit d26588b1a1f71a0b98c17cf620b0bb1542a47d11 - io_agent_mem.h identation changed from 4 to 3
Author: Your Name
Author date (UTC): 2019-11-28 03:34
Committer name: Your Name
Committer date (UTC): 2019-11-28 03:34
Parent(s): f8259daaa4477e7e5a568b15c23e6f717ce13f42
Signer:
Signing key:
Signing status: N
Tree: e22d0b59521ad74c1c0f49e2d003159fa4bbef99
File Lines added Lines deleted
include/jlib/io_agent_mem.h 206 209
File include/jlib/io_agent_mem.h changed (mode: 100644) (index 80860b0..2874de8)
10 10
11 11 namespace jl namespace jl
12 12 { {
13 /**
13 /**
14 14 * @brief io_agent_mem based on io_agent interface * @brief io_agent_mem based on io_agent interface
15 15 * *
16 16 * Uses dynamic array of fixed-size memory pools. * Uses dynamic array of fixed-size memory pools.
 
... ... namespace jl
25 25 * @see io_agent_mem::destroy * @see io_agent_mem::destroy
26 26 * @see io_agent_mem::Pos * @see io_agent_mem::Pos
27 27 */ */
28 template<uint64_t ALLOCATION_SIZE = 1024 * 1024>
29 struct io_agent_mem : io_agent
30 {
31 /**
32 * @brief Initialize io_agent_mem with defined state.
33 */
34 void init()
35 {
36 memory.init();
37 pos = end = {};
38 }
39
40 /**
28 template<uint64_t ALLOCATION_SIZE = 1024 * 1024>
29 struct io_agent_mem : io_agent
30 {
31 /**
32 * @brief Initialize io_agent_mem with defined state.
33 */
34 void init()
35 {
36 memory.init();
37 pos = end = {};
38 }
39
40 /**
41 41 * @brief Destroy all memory pools in io_agent_mem * @brief Destroy all memory pools in io_agent_mem
42 42 */ */
43 void destroy()
44 {
45 memory.destroy([](uint8_t*&p_p){jl::deallocate(&p_p);});
46 init();
47 }
48
49 /**
50 * @brief Read data from agent.
51 *
52 * @see io_agent::read
53 */
54 [[nodiscard]] int64_t read(void *dst, uint64_t size)
55 {
56 uint8_t *p_dst = reinterpret_cast<uint8_t*>(dst);
57 int64_t readed = 0;
58
59 while (size > 0)
60 {
61 uint64_t part_read_left = part_read_size_left();
62 if (part_read_left == 0)
63 return readed;
64
65 uint64_t to_write = size;
66 if (to_write > part_read_left)
67 to_write = part_read_left;
68
69 memcpy(p_dst, memory[pos.mem_i] + pos.offset, to_write);
70 p_dst += to_write;
71 readed += to_write;
72 pos.offset += to_write;
73 if (pos.offset >= ALLOCATION_SIZE)
74 {
75 ++pos.mem_i, pos.offset -= ALLOCATION_SIZE;
76 if (pos.mem_i >= memory.count())
77 return readed;
78 }
79
80 size -= to_write;
81 }
82 return readed;
83 }
84
85 /**
86 * @brief Write data to agent.
87 *
88 * @see io_agent::write
89 */
90 [[nodiscard]] int64_t write(const void *src, uint64_t size)
91 {
92 int64_t total_size = int64_t(size);
93 uint64_t size_left = this->write_size_left();
94 if (size > size_left)
43 void destroy()
44 {
45 memory.destroy([](uint8_t*&p_p){jl::deallocate(&p_p);});
46 init();
47 }
48
49 /**
50 * @brief Read data from agent.
51 *
52 * @see io_agent::read
53 */
54 [[nodiscard]] int64_t read(void *dst, uint64_t size)
55 {
56 uint8_t *p_dst = reinterpret_cast<uint8_t*>(dst);
57 int64_t readed = 0;
58
59 while (size > 0)
60 {
61 uint64_t part_read_left = part_read_size_left();
62 if (part_read_left == 0)
63 return readed;
64
65 uint64_t to_write = size;
66 if (to_write > part_read_left)
67 to_write = part_read_left;
68
69 memcpy(p_dst, memory[pos.mem_i] + pos.offset, to_write);
70 p_dst += to_write;
71 readed += to_write;
72 pos.offset += to_write;
73 if (pos.offset >= ALLOCATION_SIZE)
95 74 { {
96 uint64_t size_to_allocate = size - size_left;
97
98 uint64_t allocate_count = size_to_allocate / ALLOCATION_SIZE
99 + (size_to_allocate % ALLOCATION_SIZE > 0);
100
101 uint64_t start = memory.count();
102 if (not memory.insert_several(allocate_count,
103 [](auto *&p){p = nullptr;}))
104 return -1;
105 for (uint64_t i = start; i < memory.count(); ++i)
106 {
107 if (not allocate_bytes(&memory[i], ALLOCATION_SIZE))
108 {
109 for (uint64_t j = start; j < i; ++j)
110 jl::deallocate(&memory[j]);
111 return -1;
112 }
113 }
75 ++pos.mem_i, pos.offset -= ALLOCATION_SIZE;
76 if (pos.mem_i >= memory.count())
77 return readed;
114 78 } }
115 79
116 const uint8_t *p_src = reinterpret_cast<const uint8_t*>(src);
117
118 while (size > 0)
119 {
120 uint64_t to_write = this->part_write_size_left();
121 if (to_write > size)
122 to_write = size;
123
124 memcpy(memory[pos.mem_i] + pos.offset, p_src, to_write);
125 p_src += to_write;
126 pos.offset += to_write;
127 if (pos.offset >= ALLOCATION_SIZE)
128 ++pos.mem_i, pos.offset -= ALLOCATION_SIZE;
129 size -= to_write;
130 }
131 if (pos > end)
132 end = pos;
133 return total_size;
134 }
135
136 /**
137 * @brief Move position of memory to read/write.
138 *
139 * @see io_agent::position_move
140 */
141 [[nodiscard]] bool position_move(int64_t byte_count)
142 {
143 if (byte_count < 0)
80 size -= to_write;
81 }
82 return readed;
83 }
84
85 /**
86 * @brief Write data to agent.
87 *
88 * @see io_agent::write
89 */
90 [[nodiscard]] int64_t write(const void *src, uint64_t size)
91 {
92 int64_t total_size = int64_t(size);
93 uint64_t size_left = this->write_size_left();
94 if (size > size_left)
95 {
96 uint64_t size_to_allocate = size - size_left;
97
98 uint64_t allocate_count = size_to_allocate / ALLOCATION_SIZE
99 + (size_to_allocate % ALLOCATION_SIZE > 0);
100
101 uint64_t start = memory.count();
102 if (not memory.insert_several(allocate_count,
103 [](auto **p){*p = nullptr;}))
104 return -1;
105 for (uint64_t i = start; i < memory.count(); ++i)
144 106 { {
145 uint64_t mem_count = ALLOCATION_SIZE / uint64_t(-byte_count);
146 int64_t new_mem_i = int64_t(pos.mem_i - mem_count);
147 int64_t new_offset = int64_t(pos.offset - (uint64_t(-byte_count) - ALLOCATION_SIZE * mem_count));
148 if (new_offset < 0)
149 {
150 new_mem_i -= 1;
151 new_offset += ALLOCATION_SIZE;
152 }
153 if (new_mem_i < 0)
154 return false;
155
156 pos.mem_i = uint64_t(new_mem_i);
157 pos.offset = uint64_t(new_offset);
158 return true;
107 if (not allocate_bytes(&memory[i], ALLOCATION_SIZE))
108 {
109 for (uint64_t j = start; j < i; ++j)
110 jl::deallocate(&memory[j]);
111 return -1;
112 }
159 113 } }
160 else
161 {
162 uint64_t mem_count = ALLOCATION_SIZE / uint64_t(byte_count);
163 uint64_t new_mem_i = pos.mem_i + mem_count;
164 uint64_t new_offset = pos.offset + (uint64_t(byte_count) - ALLOCATION_SIZE * mem_count);
165 if (new_offset >= ALLOCATION_SIZE)
166 {
167 new_mem_i += 1;
168 new_offset -= ALLOCATION_SIZE;
169 }
170 if (new_mem_i >= memory.count())
171 return false;
172
173 pos.mem_i = new_mem_i;
174 pos.offset = new_offset;
175 return true;
176 }
177 }
178
179 /**
180 * @brief Get if position is at end of last memory pool.
181 *
182 * @see io_agent::is_end
183 */
184 [[nodiscard]] bool is_end() const { return not (end > pos); }
185
186 void reset_pos() { pos = {}; }
187
188 [[nodiscard]] uint64_t size() const { return end.size(); }
189
190 protected:
191 [[nodiscard]] uint64_t read_size_left() const
192 {
193 return (end - pos).size();
194 }
195 [[nodiscard]] uint64_t write_size_left() const
196 {
197 return (Pos{memory.count(), 0} - pos).size();
198 }
199
200 [[nodiscard]] uint64_t part_read_size_left() const
201 {
202 if (pos.mem_i == end.mem_i)
203 return end.offset - pos.offset;
204 return ALLOCATION_SIZE - pos.offset;
205 }
206
207 [[nodiscard]] uint64_t part_write_size_left() const
208 {
209 return ALLOCATION_SIZE - pos.offset;
210 }
211
212 /**
213 * @brief Position in io_agent_mem.
214 *
215 * @see io_agent_mem
216 */
217 struct Pos
218 {
219 [[nodiscard]] inline bool operator > (const Pos &o) const
114 }
115
116 const uint8_t *p_src = reinterpret_cast<const uint8_t*>(src);
117
118 while (size > 0)
119 {
120 uint64_t to_write = this->part_write_size_left();
121 if (to_write > size)
122 to_write = size;
123
124 memcpy(memory[pos.mem_i] + pos.offset, p_src, to_write);
125 p_src += to_write;
126 pos.offset += to_write;
127 if (pos.offset >= ALLOCATION_SIZE)
128 ++pos.mem_i, pos.offset -= ALLOCATION_SIZE;
129 size -= to_write;
130 }
131 if (pos > end)
132 end = pos;
133 return total_size;
134 }
135
136 /**
137 * @brief Move position of memory to read/write.
138 *
139 * @see io_agent::position_move
140 */
141 [[nodiscard]] bool position_move(int64_t byte_count)
142 {
143 if (byte_count < 0)
144 {
145 uint64_t mem_count = ALLOCATION_SIZE / uint64_t(-byte_count);
146 int64_t new_mem_i = int64_t(pos.mem_i - mem_count);
147 int64_t new_offset = int64_t(pos.offset -
148 (uint64_t(-byte_count)
149 - ALLOCATION_SIZE * mem_count));
150 if (new_offset < 0)
220 151 { {
221 return mem_i > o.mem_i || (mem_i == o.mem_i && offset > o.offset);
152 new_mem_i -= 1;
153 new_offset += ALLOCATION_SIZE;
222 154 } }
223 [[nodiscard]] inline Pos operator - (const Pos &o) const
155 if (new_mem_i < 0)
156 return false;
157
158 pos.mem_i = uint64_t(new_mem_i);
159 pos.offset = uint64_t(new_offset);
160 return true;
161 }
162 else
163 {
164 uint64_t mem_count = ALLOCATION_SIZE / uint64_t(byte_count);
165 uint64_t new_mem_i = pos.mem_i + mem_count;
166 uint64_t new_offset = pos.offset +
167 (uint64_t(byte_count)
168 - ALLOCATION_SIZE * mem_count);
169 if (new_offset >= ALLOCATION_SIZE)
224 170 { {
225 Pos res;
226 res.mem_i = mem_i - o.mem_i;
227 if (o.offset > offset)
228 {
229 res.mem_i -= 1;
230 res.offset = ALLOCATION_SIZE - (o.offset - offset);
231 }
232 else res.offset = offset - o.offset;
233 return res;
171 new_mem_i += 1;
172 new_offset -= ALLOCATION_SIZE;
234 173 } }
235
236 [[nodiscard]] inline uint64_t size() const
174 if (new_mem_i >= memory.count())
175 return false;
176
177 pos.mem_i = new_mem_i;
178 pos.offset = new_offset;
179 return true;
180 }
181 }
182
183 /**
184 * @brief Get if position is at end of last memory pool.
185 *
186 * @see io_agent::is_end
187 */
188 [[nodiscard]] bool is_end() const { return not (end > pos); }
189
190 void reset_pos() { pos = {}; }
191
192 [[nodiscard]] uint64_t size() const { return end.size(); }
193
194 protected:
195 [[nodiscard]] uint64_t read_size_left() const
196 { return (end - pos).size(); }
197 [[nodiscard]] uint64_t write_size_left() const
198 { return (Pos{memory.count(), 0} - pos).size(); }
199
200 [[nodiscard]] uint64_t part_read_size_left() const {
201 if (pos.mem_i == end.mem_i)
202 return end.offset - pos.offset;
203 return ALLOCATION_SIZE - pos.offset;
204 }
205
206 [[nodiscard]] uint64_t part_write_size_left() const
207 { return ALLOCATION_SIZE - pos.offset; }
208
209 /**
210 * @brief Position in io_agent_mem.
211 *
212 * @see io_agent_mem
213 */
214 struct Pos
215 {
216 [[nodiscard]] inline bool operator > (const Pos &o) const
217 {
218 return mem_i > o.mem_i || (mem_i == o.mem_i && offset > o.offset);
219 }
220 [[nodiscard]] inline Pos operator - (const Pos &o) const
221 {
222 Pos res;
223 res.mem_i = mem_i - o.mem_i;
224 if (o.offset > offset)
237 225 { {
238 return mem_i * ALLOCATION_SIZE + offset;
226 res.mem_i -= 1;
227 res.offset = ALLOCATION_SIZE - (o.offset - offset);
239 228 } }
240
241 uint64_t mem_i; ///< @brief Index of array of memory pools in io_agent_mem.
242 uint64_t offset; ///< @brief Offset of memory pool, pointed by mem_i.
243 };
244
245 darray<uint8_t*> memory; ///< @brief Array of memory pools.
246 Pos end; ///< @brief Largest position written.
247 Pos pos; ///< @brief Position for reading and writing.
248 };
229 else res.offset = offset - o.offset;
230 return res;
231 }
232
233 [[nodiscard]] inline uint64_t size() const
234 {
235 return mem_i * ALLOCATION_SIZE + offset;
236 }
237
238 uint64_t mem_i; ///< @brief Index of memory pool number in the array.
239 uint64_t offset; ///< @brief Offset of memory pool, pointed by mem_i.
240 };
241
242 darray<uint8_t*> memory; ///< @brief Array of memory pools.
243 Pos end; ///< @brief Largest position written.
244 Pos pos; ///< @brief Position for reading and writing.
245 };
249 246 } }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/Jackalope/jlib

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/Jackalope/jlib

Clone this repository using git:
git clone git://git.rocketgit.com/user/Jackalope/jlib

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main