org.tinylog.core.WritingThread Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tinylog-impl Show documentation
Show all versions of tinylog-impl Show documentation
tinylog native logging implementation
The newest version!
/*
* Copyright 2016 Martin Winandy
*
* 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.
*/
package org.tinylog.core;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.tinylog.Level;
import org.tinylog.provider.InternalLogger;
import org.tinylog.writers.Writer;
/**
* Thread for writing log entries asynchronously.
*/
public final class WritingThread extends Thread {
private static final String THREAD_NAME = "tinylog-WritingThread";
private final Object mutex;
private final Collection writers;
private List tasks;
/**
* @param writers
* Open writers
*/
WritingThread(final Collection writers) {
this.mutex = new Object();
this.writers = writers;
this.tasks = new ArrayList();
setName(THREAD_NAME);
setPriority(Thread.MIN_PRIORITY);
setDaemon(true);
}
/**
* Fetches log entries and writes them until receiving a poison task.
*/
@Override
public void run() {
Collection writers = new ArrayList(1);
while (true) {
for (Task task : receiveTasks()) {
if (task == Task.POISON) {
close();
return;
} else {
write(writers, task);
}
}
flush(writers);
writers.clear();
}
}
/**
* Adds a log entry for writing.
*
* @param writer
* Writer to write given log entry
* @param logEntry
* Log entry to write
*/
public void add(final Writer writer, final LogEntry logEntry) {
Task task = new Task(writer, logEntry);
synchronized (mutex) {
tasks.add(task);
mutex.notify();
}
}
/**
* Shuts this writing thread down after writing all already added log entries.
*
*
* This method doesn't wait until the writing thread is down. {@link Thread#join()} can be used afterwards to wait
* for termination.
*
*/
public void shutdown() {
synchronized (mutex) {
tasks.add(Task.POISON);
mutex.notify();
}
}
/**
* Receives all added log entries.
*
* @return Log entries to write
*/
private List receiveTasks() {
synchronized (mutex) {
while (tasks.isEmpty()) {
try {
mutex.wait();
} catch (InterruptedException ex) {
return Collections.emptyList();
}
}
List currentTasks = tasks;
tasks = new ArrayList();
return currentTasks;
}
}
/**
* Writes a log entry.
*
* @param writers
* Mutable collection of used writers
* @param task
* Log entry to write
*/
private void write(final Collection writers, final Task task) {
try {
Writer writer = task.writer;
writer.write(task.logEntry);
if (!writers.contains(writer)) {
writers.add(writer);
}
} catch (Exception ex) {
InternalLogger.log(Level.ERROR, ex, "Failed to write log entry '" + task.logEntry.getMessage() + "'");
}
}
/**
* Flushes a collection of writers.
*
* @param writers
* Writers to flush
*/
private void flush(final Collection writers) {
for (Writer writer : writers) {
try {
writer.flush();
} catch (Exception ex) {
InternalLogger.log(Level.ERROR, ex, "Failed to flush writer");
}
}
}
/**
* Closes all writers.
*/
private void close() {
for (Writer writer : writers) {
try {
writer.close();
} catch (Exception ex) {
InternalLogger.log(Level.ERROR, ex, "Failed to close writer");
}
}
}
/**
* Tuple that contains a log entry and a writer for outputting it.
*/
private static final class Task {
private static final Task POISON = null;
private final Writer writer;
private final LogEntry logEntry;
/**
* @param writer
* Writer for outputting log entry
* @param logEntry
* Log entry to write
*/
Task(final Writer writer, final LogEntry logEntry) {
this.writer = writer;
this.logEntry = logEntry;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy