Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-map-arena.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
44#ifndef AH_MAP_ARENA_H
45#define AH_MAP_ARENA_H
46
47// ---------------------------------------------------------------------------
48// Platform gating.
49//
50// `MapArena` depends on Linux-specific APIs that have no portable POSIX
51// counterpart:
52//
53// * `mremap()` and `MREMAP_MAYMOVE` (used by `remap()` to grow the
54// backing region in place).
55// * `MAP_POPULATE` (used to pre-fault pages on mmap).
56//
57// macOS / BSD / Windows lack these. Rather than synthesise a fragile
58// portable fallback (a `munmap()` + `mmap()` cycle invalidates every
59// pointer the caller is holding), we make `MapArena` a Linux-only
60// feature. The header is still includable on other platforms — it
61// simply declares no symbols there. Tests and clients gate their use
62// behind `ALEPH_HAS_MAP_ARENA`.
63// ---------------------------------------------------------------------------
64
65#if defined(__linux__)
66# define ALEPH_HAS_MAP_ARENA 1
67#else
68# define ALEPH_HAS_MAP_ARENA 0
69#endif
70
71#if ALEPH_HAS_MAP_ARENA
72
73#include <unistd.h>
74#include <cstdlib>
75#include <cstdint>
76#include <cassert>
77#include <filesystem>
78#include <fcntl.h>
79#include <sys/mman.h>
80#include <string>
81
82#include <ah-errors.H>
83
84namespace fs = std::filesystem;
85
86namespace Aleph
87{
88
153class MapArena
154{
155public:
156
158 static constexpr size_t initial_rgn_size = 4 * 1024;
159
160private:
161
162 char * rgn_ptr = nullptr;
163 size_t end_ = 0;
164 size_t rgn_size = initial_rgn_size;
165 int fd = -1;
166
174 bool remap(const size_t sz)
175 {
176 assert(sz > avail());
177
178 // Determine new region size according to requested sz
179 size_t new_size = 2 * rgn_size;
180 while (new_size - end_ < sz)
181 new_size *= 2;
182
184 if (ptr == MAP_FAILED)
185 return false;
186
187 const auto status = ftruncate(fd, static_cast<off_t>(new_size));
188 ah_runtime_error_unless(status == 0)
189 << "cannot truncate the file to " << new_size << " error = " << errno;
190
191 rgn_ptr = static_cast<char*>(ptr);
193
194 return true;
195 }
196
197public:
198
200 using iterator = char *;
201
203 using const_iterator = const char *;
204
206 using size_type = size_t;
207
218 void init(const std::string & file_path_name, void * addr = nullptr)
219 {
220 end_ = 0;
221 if (fs::exists(fs::path(file_path_name)))
222 {
223 fd = open(file_path_name.c_str(), O_RDWR, static_cast<mode_t>(0600));
224 ah_runtime_error_unless(fd >= 0) << "cannot open " << file_path_name;
225
226 // Read end_ value stored at the beginning of file
227 const auto status = ::read(fd, &end_, sizeof(end_));
228 ah_runtime_error_unless(status != -1)
229 << "Cannot read file length of " << file_path_name;
230
231 // Determine file size
232 const auto file_size = lseek(fd, 0, SEEK_END);
233 ah_runtime_error_unless(file_size != static_cast<off_t>(-1))
234 << "Cannot determine file length of " << file_path_name;
235 rgn_size = static_cast<size_t>(file_size);
236 }
237 else
238 {
239 fd = open(file_path_name.c_str(), O_RDWR | O_CREAT, static_cast<mode_t>(0600));
240 ah_runtime_error_unless(fd >= 0) << "cannot open " << file_path_name;
241 const auto status = ftruncate(fd, static_cast<off_t>(rgn_size));
242 ah_runtime_error_unless(status == 0)
243 << "cannot truncate the file to " << rgn_size << " error = " << errno;
244 }
245
246 void *ptr = mmap(addr, rgn_size, PROT_READ | PROT_WRITE,
249 << "Cannot mmap. Error = " << errno;
250
251 rgn_ptr = static_cast<char*>(ptr);
252 }
253
262 void init_and_erase(const std::string & file_path_name)
263 {
264 fs::remove(file_path_name);
266 }
267
278 explicit MapArena(const std::string & file_path_name)
279 {
281 }
282
287 MapArena() noexcept = default;
288
290 MapArena(const MapArena &) = delete;
291
293 MapArena & operator=(const MapArena &) = delete;
294
302 : rgn_ptr(other.rgn_ptr), end_(other.end_),
303 rgn_size(other.rgn_size), fd(other.fd)
304 {
305 other.rgn_ptr = nullptr;
306 other.end_ = 0;
307 other.rgn_size = initial_rgn_size;
308 other.fd = -1;
309 }
310
316 MapArena & operator=(MapArena && other) noexcept
317 {
318 if (this != &other)
319 {
320 // Clean up current resources
321 if (rgn_ptr)
323 if (fd != -1)
324 close(fd);
325
326 // Transfer ownership
327 rgn_ptr = other.rgn_ptr;
328 end_ = other.end_;
329 rgn_size = other.rgn_size;
330 fd = other.fd;
331
332 // Invalidate other
333 other.rgn_ptr = nullptr;
334 other.end_ = 0;
335 other.rgn_size = initial_rgn_size;
336 other.fd = -1;
337 }
338 return *this;
339 }
340
343 ~MapArena()
344 {
345 if (rgn_ptr)
347 if (fd != -1)
348 close(fd);
349 }
350
355 [[nodiscard]] iterator begin() noexcept { return rgn_ptr; }
356
361 [[nodiscard]] const_iterator begin() const noexcept { return rgn_ptr; }
362
367 [[nodiscard]] iterator end() noexcept { return rgn_ptr + end_; }
368
373 [[nodiscard]] const_iterator end() const noexcept { return rgn_ptr + end_; }
374
382 [[nodiscard]] char * base() const noexcept { return rgn_ptr; }
383
390 [[nodiscard]] size_type avail() const noexcept
391 {
392 return rgn_size - end_;
393 }
394
409 [[nodiscard]] char * reserve(const size_type sz)
410 {
411 if (sz > avail() && !remap(sz))
412 return nullptr;
413
414 return rgn_ptr + end_;
415 }
416
429 void commit(const size_type sz) noexcept
430 {
431 end_ += sz;
432 }
433
439 void sync() noexcept
440 {
442 }
443
448 [[nodiscard]] size_type size() const noexcept
449 {
450 return end_;
451 }
452
457 [[nodiscard]] size_type capacity() const noexcept
458 {
459 return rgn_size;
460 }
461
466 [[nodiscard]] bool empty() const noexcept
467 {
468 return end_ == 0;
469 }
470
475 [[nodiscard]] bool is_initialized() const noexcept
476 {
477 return rgn_ptr != nullptr;
478 }
479
484 [[nodiscard]] void * mapped_addr() const noexcept
485 {
486 return rgn_ptr;
487 }
488
493 [[nodiscard]] int file_descriptor() const noexcept
494 {
495 return fd;
496 }
497
504 friend std::ostream & operator<<(std::ostream & o, const MapArena & s)
505 {
506 return o << "MapArena:\n"
507 << " rgn_ptr = " << static_cast<void*>(s.rgn_ptr) << '\n'
508 << " end_ = " << s.end_ << '\n'
509 << " rgn_size = " << s.rgn_size << '\n'
510 << " size = " << s.size() << '\n'
511 << " capacity = " << s.capacity() << '\n'
512 << " avail = " << s.avail();
513 }
514};
515
516} // end namespace Aleph
517
518#endif // ALEPH_HAS_MAP_ARENA
519
520#endif // AH_MAP_ARENA_H
Exception handling system with formatted messages for Aleph-w.
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
Definition ah-errors.H:255
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
size_t size(Node *root) noexcept
size_t size_type
Definition ahAlgo.H:55
std::ostream & operator<<(std::ostream &osObject, const Field< T > &rightOp)
Definition ahField.H:121
static std::atomic< bool > init
Definition hash-fct.C:54