
Author: ceki Date: Fri Dec 5 17:53:29 2008 New Revision: 2071 Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java Log: - using explicit locks instead of relying on the internal details of the collection returned by Collections.synchronizedList() Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java Fri Dec 5 17:53:29 2008 @@ -1,16 +1,15 @@ /** - * LOGBack: the reliable, fast and flexible logging library for Java. - * - * Copyright (C) 1999-2006, QOS.ch - * - * This library is free software, you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation. + * Logback: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 2000-2008, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. */ package ch.qos.logback.core; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import ch.qos.logback.core.status.Status; @@ -21,23 +20,24 @@ public static final int MAX_COUNT = 200; - // This method is synchronized on the instance. - // Code int count = 0; - // reading SynchronizedCollection source code, we learn that the mutex is the - // returned synchronized list, we make use of this fact in getCopyOfStatusList // protected access was requested in http://jira.qos.ch/browse/LBCORE-36 - final protected List<Status> statusList = Collections - .synchronizedList(new ArrayList<Status>()); + final protected List<Status> statusList = new ArrayList<Status>(); + final protected Object statusListLock = new Object(); + int level = Status.INFO; - // reading SynchronizedCollection source code, we learn that the mutex is the - // returned synchronized list, we make use of this fact in - // getCopyOfStatusListnerList // protected access was requested in http://jira.qos.ch/browse/LBCORE-36 - final protected List<StatusListener> statusListenerList = Collections - .synchronizedList(new ArrayList<StatusListener>()); + final protected List<StatusListener> statusListenerList = new ArrayList<StatusListener>(); + final protected Object statusListenerListLock = new Object(); + + // Note on synchronization + // This class contains two separate locks statusListLock and + // statusListenerListLock guarding respectively the statusList and + // statusListenerList fields. The locks are used internally + // without cycles. They are exposed to derived classes which should be careful + // not to create deadlock cycles. /** * Add a new status object. @@ -46,9 +46,9 @@ * the status message to add */ public void add(Status newStatus) { - // LBCORE-72: fire event before the count check + // LBCORE-72: fire event before the count check fireStatusAddEvent(newStatus); - + if (count > MAX_COUNT) { return; } @@ -57,12 +57,15 @@ if (newStatus.getLevel() > level) { level = newStatus.getLevel(); } - statusList.add(newStatus); + + synchronized (statusListLock) { + statusList.add(newStatus); + } } private void fireStatusAddEvent(Status status) { - synchronized (statusListenerList) { + synchronized (statusListenerListLock) { for (StatusListener sl : statusListenerList) { sl.addStatusEvent(status); } @@ -70,7 +73,7 @@ } public List<Status> getCopyOfStatusList() { - synchronized (statusList) { + synchronized (statusListLock) { return new ArrayList<Status>(statusList); } } @@ -84,15 +87,19 @@ } public void add(StatusListener listener) { - statusListenerList.add(listener); + synchronized (statusListenerListLock) { + statusListenerList.add(listener); + } } public void remove(StatusListener listener) { - statusListenerList.remove(listener); + synchronized (statusListenerListLock) { + statusListenerList.remove(listener); + } } public List<StatusListener> getCopyOfStatusListenerList() { - synchronized (statusListenerList) { + synchronized (statusListenerListLock) { return new ArrayList<StatusListener>(statusListenerList); } }