Files
filament/libs/utils/src/Log.cpp
Mathias Agopian 047543a4a6 make our ostream thread safe
ostream internals are now protected by a lock, which ensures the
internal state stays consistant, however, this won't prevent 
multiple threads to have their output ominterfering with each other,
which is no different from the stl behavior.


This fixes #4992
2022-01-10 15:04:26 -08:00

116 lines
3.1 KiB
C++

/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <utils/Log.h>
#include <string>
#include <utils/compiler.h>
#ifdef __ANDROID__
# include <android/log.h>
# ifndef UTILS_LOG_TAG
# define UTILS_LOG_TAG "Filament"
# endif
#endif
namespace utils {
namespace io {
class LogStream : public ostream {
public:
enum Priority {
LOG_DEBUG, LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_VERBOSE
};
explicit LogStream(Priority p) noexcept : mPriority(p) {}
ostream& flush() noexcept override;
private:
Priority mPriority;
};
ostream& LogStream::flush() noexcept {
std::lock_guard lock(mLock);
Buffer& buf = getBuffer();
#ifdef __ANDROID__
switch (mPriority) {
case LOG_DEBUG:
__android_log_write(ANDROID_LOG_DEBUG, UTILS_LOG_TAG, buf.get());
break;
case LOG_ERROR:
__android_log_write(ANDROID_LOG_ERROR, UTILS_LOG_TAG, buf.get());
break;
case LOG_WARNING:
__android_log_write(ANDROID_LOG_WARN, UTILS_LOG_TAG, buf.get());
break;
case LOG_INFO:
__android_log_write(ANDROID_LOG_INFO, UTILS_LOG_TAG, buf.get());
break;
case LOG_VERBOSE:
__android_log_write(ANDROID_LOG_VERBOSE, UTILS_LOG_TAG, buf.get());
break;
}
#else // ANDROID
switch (mPriority) {
case LOG_DEBUG:
case LOG_WARNING:
case LOG_INFO:
fprintf(stdout, "%s", buf.get());
break;
case LOG_ERROR:
fprintf(stderr, "%s", buf.get());
break;
case LOG_VERBOSE:
#ifndef NDEBUG
fprintf(stdout, "%s", buf.get());
#endif
break;
}
#endif // ANDROID
buf.reset();
return *this;
}
/*
* We can't use thread_local because on Android we're currently using several dynamic libraries
* including this .o (via libutils.a), which violates the ODR and ends-up with only one of
* the thread_local instance initialized.
* For this reason, ostream is protected by a mutex instead.
*/
static LogStream cout(LogStream::Priority::LOG_DEBUG);
static LogStream cerr(LogStream::Priority::LOG_ERROR);
static LogStream cwarn(LogStream::Priority::LOG_WARNING);
static LogStream cinfo(LogStream::Priority::LOG_INFO);
static LogStream cverbose(LogStream::Priority::LOG_VERBOSE);
} // namespace io
Loggers const slog = {
io::cout, // debug
io::cerr, // error
io::cwarn, // warning
io::cinfo, // info
io::cverbose // verbose
};
} // namespace utils