Skip to content

Commit 5fb623d

Browse files
author
moonshadow565
committed
posix support
1 parent 1b858a5 commit 5fb623d

File tree

3 files changed

+177
-50
lines changed

3 files changed

+177
-50
lines changed

dep/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ if(NOT zstd_POPULATED)
5555
add_library(zstd STATIC ${zstd_SRCS})
5656
target_include_directories(zstd PUBLIC ${zstd_SOURCE_DIR}/lib)
5757
target_include_directories(zstd PRIVATE ${zstd_SOURCE_DIR}/lib/common)
58+
target_compile_definitions(zstd PRIVATE -DZSTD_DISABLE_ASM)
5859
target_compile_definitions(zstd INTERFACE -DZSTD_STATIC_LINKING_ONLY)
5960
if(MSVC)
6061
target_compile_options(zstd PRIVATE /wd4267)

lib/rlib/iofile.cpp

+175-50
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,52 @@
99

1010
using namespace rlib;
1111

12+
struct NoInterupt {
13+
NoInterupt(bool no_interupt) : no_interupt(no_interupt) {
14+
if (no_interupt) {
15+
while (lock_)
16+
;
17+
++count_;
18+
}
19+
}
20+
~NoInterupt() {
21+
if (no_interupt) {
22+
while (lock_)
23+
;
24+
--count_;
25+
}
26+
}
27+
28+
private:
29+
bool no_interupt;
30+
static std::atomic_int lock_;
31+
static std::atomic_int count_;
32+
};
33+
34+
auto IO::File::shrink_to_fit() noexcept -> bool {
35+
if (!impl_.fd || !(impl_.flags & WRITE)) {
36+
return false;
37+
}
38+
return true;
39+
}
40+
41+
auto IO::File::reserve(std::size_t offset, std::size_t count) noexcept -> bool {
42+
if (!impl_.fd || !(impl_.flags & WRITE)) {
43+
return false;
44+
}
45+
return true;
46+
}
47+
48+
auto IO::File::copy(std::size_t offset, std::size_t count) const -> std::span<char const> {
49+
thread_local auto result = std::vector<char>();
50+
if (result.size() < count) {
51+
result.clear();
52+
result.resize(count);
53+
}
54+
rlib_assert(this->read(offset, {result.data(), count}));
55+
return {result.data(), count};
56+
}
57+
1258
#ifdef _WIN32
1359
# ifndef NOMINMAX
1460
# define NOMINMAX
@@ -18,13 +64,13 @@ using namespace rlib;
1864
# endif
1965
# include <windows.h>
2066

21-
static std::atomic_int NoInterupt_lock_ = 0;
22-
static std::atomic_int NoInterupt_count_ = [] {
67+
std::atomic_int NoInterupt::lock_ = 0;
68+
std::atomic_int NoInterupt::count_ = [] {
2369
SetConsoleCtrlHandler(
2470
+[](DWORD) -> BOOL {
25-
++NoInterupt_lock_;
26-
if (NoInterupt_count_) {
27-
--NoInterupt_lock_;
71+
++lock_;
72+
if (count_) {
73+
--lock_;
2874
return TRUE;
2975
}
3076
return FALSE;
@@ -33,26 +79,6 @@ static std::atomic_int NoInterupt_count_ = [] {
3379
return 0;
3480
}();
3581

36-
struct NoInterupt {
37-
NoInterupt(bool no_interupt) : no_interupt(no_interupt) {
38-
if (no_interupt) {
39-
while (NoInterupt_lock_)
40-
;
41-
++NoInterupt_count_;
42-
}
43-
}
44-
~NoInterupt() {
45-
if (no_interupt) {
46-
while (NoInterupt_lock_)
47-
;
48-
--NoInterupt_count_;
49-
}
50-
}
51-
52-
private:
53-
bool no_interupt;
54-
};
55-
5682
IO::File::File(fs::path const& path, Flags flags) {
5783
rlib_trace("path: %s\n", path.generic_string().c_str());
5884
if ((flags & WRITE) && path.has_parent_path()) {
@@ -88,20 +114,6 @@ IO::File::~File() noexcept {
88114
}
89115
}
90116

91-
auto IO::File::shrink_to_fit() noexcept -> bool {
92-
if (!impl_.fd || !(impl_.flags & WRITE)) {
93-
return false;
94-
}
95-
return true;
96-
}
97-
98-
auto IO::File::reserve(std::size_t offset, std::size_t count) noexcept -> bool {
99-
if (!impl_.fd || !(impl_.flags & WRITE)) {
100-
return false;
101-
}
102-
return true;
103-
}
104-
105117
auto IO::File::resize(std::size_t offset, std::size_t count) noexcept -> bool {
106118
if (!impl_.fd || !(impl_.flags & WRITE)) {
107119
return false;
@@ -170,16 +182,6 @@ auto IO::File::write(std::uint64_t offset, std::span<char const> src) noexcept -
170182
return true;
171183
}
172184

173-
auto IO::File::copy(std::size_t offset, std::size_t count) const -> std::span<char const> {
174-
thread_local auto result = std::vector<char>();
175-
if (result.size() < count) {
176-
result.clear();
177-
result.resize(count);
178-
}
179-
rlib_assert(this->read(offset, {result.data(), count}));
180-
return {result.data(), count};
181-
}
182-
183185
auto IO::MMap::Impl::remap(std::size_t count) noexcept -> bool {
184186
void* data = nullptr;
185187
if (count) {
@@ -206,7 +208,130 @@ auto IO::MMap::Impl::remap(std::size_t count) noexcept -> bool {
206208
}
207209

208210
#else
209-
# error "TODO: implement linux version"
211+
# include <fcntl.h>
212+
# include <signal.h>
213+
# include <sys/mman.h>
214+
# include <sys/param.h>
215+
# include <sys/stat.h>
216+
# include <unistd.h>
217+
std::atomic_int NoInterupt::lock_ = 0;
218+
std::atomic_int NoInterupt::count_ = [] {
219+
signal(SIGINT, [](int) {
220+
++lock_;
221+
if (count_) {
222+
--lock_;
223+
} else {
224+
exit(1);
225+
}
226+
});
227+
return 0;
228+
}();
229+
230+
IO::File::File(fs::path const& path, Flags flags) {
231+
rlib_trace("path: %s\n", path.generic_string().c_str());
232+
if ((flags & WRITE) && path.has_parent_path()) {
233+
fs::create_directories(path.parent_path());
234+
}
235+
int fd = 0;
236+
if (flags & WRITE) {
237+
fd = ::open(path.string().c_str(), O_RDWR | O_CREAT, 0644);
238+
} else {
239+
fd = ::open(path.string().c_str(), O_RDONLY);
240+
}
241+
if (!fd || fd == -1) [[unlikely]] {
242+
auto ec = std::error_code((int)errno, std::system_category());
243+
throw_error("::open: ", ec);
244+
}
245+
struct ::stat size = {};
246+
if (::fstat(fd, &size) == -1) [[unlikely]] {
247+
auto ec = std::error_code((int)errno, std::system_category());
248+
throw_error("::fstat: ", ec);
249+
}
250+
impl_ = {.fd = (std::intptr_t)fd, .size = (std::size_t)size.st_size, .flags = flags};
251+
}
252+
253+
IO::File::~File() noexcept {
254+
if (auto impl = std::exchange(impl_, {}); impl.fd) {
255+
::close((int)impl.fd);
256+
}
257+
}
258+
259+
auto IO::File::resize(std::size_t offset, std::size_t count) noexcept -> bool {
260+
if (!impl_.fd || !(impl_.flags & WRITE)) {
261+
return false;
262+
}
263+
std::uint64_t const total = (std::uint64_t)offset + count;
264+
if (total < offset || total < count) {
265+
return false;
266+
}
267+
if (impl_.size == total) {
268+
return true;
269+
}
270+
if (::ftruncate((int)impl_.fd, (off_t)total) == -1) [[unlikely]] {
271+
return false;
272+
}
273+
impl_.size = total;
274+
return true;
275+
}
276+
277+
auto IO::File::read(std::size_t offset, std::span<char> dst) const noexcept -> bool {
278+
if (!impl_.fd) {
279+
return false;
280+
}
281+
while (!dst.empty()) {
282+
auto got = ::pread((int)impl_.fd, dst.data(), dst.size(), offset);
283+
if (got <= 0 || (std::size_t)got > dst.size()) {
284+
return false;
285+
}
286+
dst = dst.subspan(got);
287+
offset += got;
288+
}
289+
return true;
290+
}
291+
292+
auto IO::File::write(std::uint64_t offset, std::span<char const> src) noexcept -> bool {
293+
constexpr std::size_t CHUNK = 0x4000'0000;
294+
if (!impl_.fd || !(impl_.flags & WRITE)) {
295+
return false;
296+
}
297+
std::size_t const write_end = offset + src.size();
298+
if (write_end < offset || write_end < src.size()) {
299+
return false;
300+
}
301+
NoInterupt no_interupt_lock(impl_.flags & NO_INTERUPT);
302+
while (!src.empty()) {
303+
auto got = ::pwrite((int)impl_.fd, src.data(), src.size(), offset);
304+
if (got <= 0 || (std::size_t)got > src.size()) {
305+
return false;
306+
}
307+
src = src.subspan(got);
308+
offset += got;
309+
}
310+
if (write_end > impl_.size) {
311+
impl_.size = write_end;
312+
}
313+
return true;
314+
}
315+
316+
auto IO::MMap::Impl::remap(std::size_t count) noexcept -> bool {
317+
void* data = nullptr;
318+
if (count) {
319+
auto const fd = this->file.fd();
320+
auto const flags = this->file.flags();
321+
auto const prot = (flags & WRITE) ? PROT_READ | PROT_WRITE : PROT_READ;
322+
data = ::mmap(0, count, prot, MAP_SHARED, (int)fd, 0);
323+
if (!data || (std::intptr_t)data != -1) [[unlikely]] {
324+
return false;
325+
}
326+
}
327+
if (this->data) {
328+
::munmap(this->data, this->capacity);
329+
}
330+
this->data = data;
331+
this->capacity = count;
332+
return true;
333+
}
334+
210335
#endif
211336

212337
IO::MMap::MMap(fs::path const& path, Flags flags) {

lib/rlib/iofile.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <optional>
55
#include <span>
66
#include <system_error>
7+
#include <utility>
78

89
namespace rlib {
910
namespace fs = std::filesystem;

0 commit comments

Comments
 (0)