1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "chre/platform/shared/platform_log.h" 18 19 #include <cstdarg> 20 #include <cstdio> 21 #include <iostream> 22 23 namespace chre { 24 25 void PlatformLogBase::logLooper() { 26 while (1) { 27 std::unique_ptr<char> logMessage; 28 29 { 30 std::unique_lock<std::mutex> lock(mMutex); 31 mConditionVariable.wait(lock, [this]{ 32 return (!mLogQueue.empty() || mStopLogger); 33 }); 34 35 if (!mLogQueue.empty()) { 36 // Move the log message to avoid holding a lock for longer than 37 // required. 38 logMessage = std::move(mLogQueue.front()); 39 mLogQueue.pop(); 40 } else if (mStopLogger) { 41 // The stop logger is checked in an else-if to allow the main log queue 42 // to drain when the logger is stopping. 43 break; 44 } 45 } 46 47 // If we get here, there must be a log message to output. This is outside of 48 // the context of the lock which means that the logging thread will only be 49 // blocked for the minimum amount of time. 50 std::cerr << logMessage.get() << std::endl; 51 } 52 } 53 54 PlatformLog::PlatformLog() { 55 mLoggerThread = std::thread(&PlatformLog::logLooper, this); 56 } 57 58 PlatformLog::~PlatformLog() { 59 { 60 std::unique_lock<std::mutex> lock(mMutex); 61 mStopLogger = true; 62 mConditionVariable.notify_one(); 63 } 64 65 mLoggerThread.join(); 66 } 67 68 void PlatformLog::log(const char *formatStr, ...) { 69 char *formattedStr; 70 va_list argList; 71 va_start(argList, formatStr); 72 int result = vasprintf(&formattedStr, formatStr, argList); 73 va_end(argList); 74 75 if (result >= 0) { 76 // Wrap the formatted string into a unique_ptr so that it will be free'd 77 // once it has been logged. 78 std::unique_ptr<char> log(formattedStr); 79 80 std::unique_lock<std::mutex> lock(mMutex); 81 mLogQueue.push(std::move(log)); 82 mConditionVariable.notify_one(); 83 } else { 84 std::cerr << "Failed to allocate log message" << std::endl; 85 abort(); 86 } 87 } 88 89 } // namespace chre 90