Move TsCerr to separate header.

This commit is contained in:
levlam 2021-05-18 17:24:32 +03:00
parent 674a112bfa
commit df4c4b9471
6 changed files with 101 additions and 68 deletions

View File

@ -12,6 +12,7 @@
#include "td/utils/filesystem.h" #include "td/utils/filesystem.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/misc.h" #include "td/utils/misc.h"
#include "td/utils/TsCerr.h"
#include <algorithm> #include <algorithm>
#include <cstdlib> #include <cstdlib>

View File

@ -114,6 +114,7 @@ set(TDUTILS_SOURCE
td/utils/TsFileLog.cpp td/utils/TsFileLog.cpp
td/utils/tl_parsers.cpp td/utils/tl_parsers.cpp
td/utils/translit.cpp td/utils/translit.cpp
td/utils/TsCerr.cpp
td/utils/TsFileLog.cpp td/utils/TsFileLog.cpp
td/utils/unicode.cpp td/utils/unicode.cpp
td/utils/utf8.cpp td/utils/utf8.cpp
@ -257,6 +258,7 @@ set(TDUTILS_SOURCE
td/utils/tl_parsers.h td/utils/tl_parsers.h
td/utils/tl_storers.h td/utils/tl_storers.h
td/utils/translit.h td/utils/translit.h
td/utils/TsCerr.h
td/utils/TsFileLog.h td/utils/TsFileLog.h
td/utils/TsList.h td/utils/TsList.h
td/utils/type_traits.h td/utils/type_traits.h

View File

@ -0,0 +1,64 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/utils/TsCerr.h"
#include "td/utils/ExitGuard.h"
#include "td/utils/port/StdStreams.h"
#include "td/utils/Time.h"
#include <cerrno>
namespace td {
std::atomic_flag TsCerr::lock_ = ATOMIC_FLAG_INIT;
TsCerr::TsCerr() {
enterCritical();
}
TsCerr::~TsCerr() {
exitCritical();
}
TsCerr &TsCerr::operator<<(Slice slice) {
auto &fd = Stderr();
if (fd.empty()) {
return *this;
}
double end_time = 0;
while (!slice.empty()) {
auto res = fd.write(slice);
if (res.is_error()) {
if (res.error().code() == EPIPE) {
break;
}
// Resource temporary unavailable
if (end_time == 0) {
end_time = Time::now() + 0.01;
} else if (Time::now() > end_time) {
break;
}
continue;
}
slice.remove_prefix(res.ok());
}
return *this;
}
void TsCerr::enterCritical() {
while (lock_.test_and_set(std::memory_order_acquire) && !ExitGuard::is_exited()) {
// spin
}
}
void TsCerr::exitCritical() {
lock_.clear(std::memory_order_release);
}
static ExitGuard exit_guard;
} // namespace td

33
tdutils/td/utils/TsCerr.h Normal file
View File

@ -0,0 +1,33 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/Slice.h"
#include <atomic>
namespace td {
class TsCerr {
public:
TsCerr();
TsCerr(const TsCerr &) = delete;
TsCerr &operator=(const TsCerr &) = delete;
TsCerr(TsCerr &&) = delete;
TsCerr &operator=(TsCerr &&) = delete;
~TsCerr();
TsCerr &operator<<(Slice slice);
private:
static std::atomic_flag lock_;
void enterCritical();
void exitCritical();
};
} // namespace td

View File

@ -8,10 +8,9 @@
#include "td/utils/ExitGuard.h" #include "td/utils/ExitGuard.h"
#include "td/utils/port/Clocks.h" #include "td/utils/port/Clocks.h"
#include "td/utils/port/StdStreams.h"
#include "td/utils/port/thread_local.h" #include "td/utils/port/thread_local.h"
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
#include "td/utils/Time.h" #include "td/utils/TsCerr.h"
#include <atomic> #include <atomic>
#include <cstdlib> #include <cstdlib>
@ -151,54 +150,6 @@ Logger::~Logger() {
} }
} }
TsCerr::TsCerr() {
enterCritical();
}
TsCerr::~TsCerr() {
exitCritical();
}
TsCerr &TsCerr::operator<<(Slice slice) {
auto &fd = Stderr();
if (fd.empty()) {
return *this;
}
double end_time = 0;
while (!slice.empty()) {
auto res = fd.write(slice);
if (res.is_error()) {
if (res.error().code() == EPIPE) {
break;
}
// Resource temporary unavailable
if (end_time == 0) {
end_time = Time::now() + 0.01;
} else if (Time::now() > end_time) {
break;
}
continue;
}
slice.remove_prefix(res.ok());
}
return *this;
}
void TsCerr::enterCritical() {
while (lock_.test_and_set(std::memory_order_acquire) && !ExitGuard::is_exited()) {
// spin
}
}
void TsCerr::exitCritical() {
lock_.clear(std::memory_order_release);
}
TsCerr::Lock TsCerr::lock_ = ATOMIC_FLAG_INIT;
void TsLog::enter_critical() {
while (lock_.test_and_set(std::memory_order_acquire) && !ExitGuard::is_exited()) {
// spin
}
}
void TsLog::exit_critical() { void TsLog::exit_critical() {
lock_.clear(std::memory_order_release); lock_.clear(std::memory_order_release);
} }

View File

@ -185,24 +185,6 @@ extern LogInterface *log_interface;
using OnLogMessageCallback = void (*)(int verbosity_level, CSlice message); using OnLogMessageCallback = void (*)(int verbosity_level, CSlice message);
void set_log_message_callback(int max_verbosity_level, OnLogMessageCallback callback); void set_log_message_callback(int max_verbosity_level, OnLogMessageCallback callback);
class TsCerr {
public:
TsCerr();
TsCerr(const TsCerr &) = delete;
TsCerr &operator=(const TsCerr &) = delete;
TsCerr(TsCerr &&) = delete;
TsCerr &operator=(TsCerr &&) = delete;
~TsCerr();
TsCerr &operator<<(Slice slice);
private:
using Lock = std::atomic_flag;
static Lock lock_;
void enterCritical();
void exitCritical();
};
class Logger { class Logger {
static const size_t BUFFER_SIZE = 128 * 1024; static const size_t BUFFER_SIZE = 128 * 1024;