Improve buffering

This commit is contained in:
Victor Zverovich 2024-01-27 16:01:15 -08:00
parent af44c29744
commit 28afff363c

View File

@ -1467,6 +1467,8 @@ template <typename F> class file_base {
if (ungetc(c, file_) == EOF) if (ungetc(c, file_) == EOF)
FMT_THROW(system_error(errno, FMT_STRING("ungetc failed"))); FMT_THROW(system_error(errno, FMT_STRING("ungetc failed")));
} }
void flush() { fflush(this->file_); }
}; };
// A FILE wrapper for glibc. // A FILE wrapper for glibc.
@ -1477,10 +1479,6 @@ template <typename F> class glibc_file : public file_base<F> {
unbuffered = 2 // _IO_UNBUFFERED unbuffered = 2 // _IO_UNBUFFERED
}; };
auto available_space() const -> ptrdiff_t {
return this->file_->_IO_buf_end - this->file_->_IO_write_ptr;
}
public: public:
using file_base<F>::file_base; using file_base<F>::file_base;
@ -1495,16 +1493,16 @@ template <typename F> class glibc_file : public file_base<F> {
--this->file_->_IO_write_ptr; --this->file_->_IO_write_ptr;
} }
// Returns the file's read buffer as a string_view. // Returns the file's read buffer.
auto get_read_buffer() const -> span<const char> { auto get_read_buffer() const -> span<const char> {
return {this->file_->_IO_read_ptr, auto ptr = this->file_->_IO_read_ptr;
to_unsigned(this->file_->_IO_read_end - this->file_->_IO_read_ptr)}; return {ptr, to_unsigned(this->file_->_IO_read_end - ptr)};
} }
// Returns the file's write buffer.
auto get_write_buffer() const -> span<char> { auto get_write_buffer() const -> span<char> {
if (available_space() == 0) fflush_unlocked(this->file_); auto ptr = this->file_->_IO_write_ptr;
FMT_ASSERT(available_space() > 0, ""); return {ptr, to_unsigned(this->file_->_IO_buf_end - ptr)};
return {this->file_->_IO_write_ptr, static_cast<size_t>(available_space())};
} }
void advance_write_buffer(size_t size) { this->file_->_IO_write_ptr += size; } void advance_write_buffer(size_t size) { this->file_->_IO_write_ptr += size; }
@ -1514,6 +1512,8 @@ template <typename F> class glibc_file : public file_base<F> {
char* end = this->file_->_IO_write_end; char* end = this->file_->_IO_write_end;
return memchr(end, '\n', to_unsigned(this->file_->_IO_write_ptr - end)); return memchr(end, '\n', to_unsigned(this->file_->_IO_write_ptr - end));
} }
void flush() { fflush_unlocked(this->file_); }
}; };
// A FILE wrapper for Apple's libc. // A FILE wrapper for Apple's libc.
@ -1524,10 +1524,6 @@ template <typename F> class apple_file : public file_base<F> {
unbuffered = 2 // __SLBF unbuffered = 2 // __SLBF
}; };
auto available_space() const -> ptrdiff_t {
return this->file_->_bf._base + this->file_->_bf._size - this->file_->_p;
}
public: public:
using file_base<F>::file_base; using file_base<F>::file_base;
@ -1549,10 +1545,9 @@ template <typename F> class apple_file : public file_base<F> {
} }
auto get_write_buffer() const -> span<char> { auto get_write_buffer() const -> span<char> {
if (available_space() == 0) fflush(this->file_);
FMT_ASSERT(available_space() > 0, "");
return {reinterpret_cast<char*>(this->file_->_p), return {reinterpret_cast<char*>(this->file_->_p),
static_cast<size_t>(available_space())}; to_unsigned(this->file_->_bf._base + this->file_->_bf._size -
this->file_->_p)};
} }
void advance_write_buffer(size_t size) { void advance_write_buffer(size_t size) {
@ -1586,6 +1581,8 @@ template <typename F> class fallback_file : public file_base<F> {
auto get_write_buffer() const -> span<char> { return {nullptr, 0}; } auto get_write_buffer() const -> span<char> { return {nullptr, 0}; }
void advance_write_buffer(size_t) {}
auto get() -> int { auto get() -> int {
has_next_ = false; has_next_ = false;
return file_base<F>::get(); return file_base<F>::get();
@ -1596,8 +1593,6 @@ template <typename F> class fallback_file : public file_base<F> {
next_ = c; next_ = c;
has_next_ = true; has_next_ = true;
} }
void advance_write_buffer(size_t) {}
}; };
template <typename F, FMT_ENABLE_IF(sizeof(F::_p) != 0)> template <typename F, FMT_ENABLE_IF(sizeof(F::_p) != 0)>
@ -1616,15 +1611,13 @@ class file_print_buffer : public buffer<char> {
private: private:
file_ref file_; file_ref file_;
void set_buffer() { static void grow(buffer<char>& base, size_t) {
auto buf = file_.get_write_buffer(); auto& self = static_cast<file_print_buffer&>(base);
this->set(buf.data, buf.size);
}
static void grow(buffer<char>& buf, size_t) {
auto& self = static_cast<file_print_buffer&>(buf);
self.file_.advance_write_buffer(self.size()); self.file_.advance_write_buffer(self.size());
self.set_buffer(); if (self.file_.get_write_buffer().size == 0) self.file_.flush();
auto buf = self.file_.get_write_buffer();
FMT_ASSERT(buf.size > 0, "");
self.set(buf.data, buf.size);
self.clear(); self.clear();
} }
@ -1632,7 +1625,8 @@ class file_print_buffer : public buffer<char> {
explicit file_print_buffer(FILE* f) : buffer(grow, size_t()), file_(f) { explicit file_print_buffer(FILE* f) : buffer(grow, size_t()), file_(f) {
flockfile(f); flockfile(f);
file_.init_buffer(); file_.init_buffer();
set_buffer(); auto buf = file_.get_write_buffer();
set(buf.data, buf.size);
} }
~file_print_buffer() { ~file_print_buffer() {
file_.advance_write_buffer(size()); file_.advance_write_buffer(size());