#region Apache License // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you 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. // #endregion using System; using System.Collections; namespace log4net.Util { /// /// Implementation of Properties collection for the /// /// /// /// This class implements a properties collection that is thread safe and supports both /// storing properties and capturing a read only copy of the current propertied. /// /// /// This class is optimized to the scenario where the properties are read frequently /// and are modified infrequently. /// /// /// Nicko Cadell public sealed class GlobalContextProperties : ContextPropertiesBase { #region Private Instance Fields /// /// The read only copy of the properties. /// /// /// /// This variable is declared volatile to prevent the compiler and JIT from /// reordering reads and writes of this thread performed on different threads. /// /// #if NETCF private ReadOnlyPropertiesDictionary m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); #else private volatile ReadOnlyPropertiesDictionary m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); #endif /// /// Lock object used to synchronize updates within this instance /// private readonly object m_syncRoot = new object(); #endregion Private Instance Fields #region Public Instance Constructors /// /// Constructor /// /// /// /// Initializes a new instance of the class. /// /// internal GlobalContextProperties() { } #endregion Public Instance Constructors #region Public Instance Properties /// /// Gets or sets the value of a property /// /// /// The value for the property with the specified key /// /// /// /// Reading the value for a key is faster than setting the value. /// When the value is written a new read only copy of /// the properties is created. /// /// override public object this[string key] { get { return m_readOnlyProperties[key]; } set { lock(m_syncRoot) { PropertiesDictionary mutableProps = new PropertiesDictionary(m_readOnlyProperties); mutableProps[key] = value; m_readOnlyProperties = new ReadOnlyPropertiesDictionary(mutableProps); } } } #endregion Public Instance Properties #region Public Instance Methods /// /// Remove a property from the global context /// /// the key for the entry to remove /// /// /// Removing an entry from the global context properties is relatively expensive compared /// with reading a value. /// /// public void Remove(string key) { lock(m_syncRoot) { if (m_readOnlyProperties.Contains(key)) { PropertiesDictionary mutableProps = new PropertiesDictionary(m_readOnlyProperties); mutableProps.Remove(key); m_readOnlyProperties = new ReadOnlyPropertiesDictionary(mutableProps); } } } /// /// Clear the global context properties /// public void Clear() { lock(m_syncRoot) { m_readOnlyProperties = new ReadOnlyPropertiesDictionary(); } } #endregion Public Instance Methods #region Internal Instance Methods /// /// Get a readonly immutable copy of the properties /// /// the current global context properties /// /// /// This implementation is fast because the GlobalContextProperties class /// stores a readonly copy of the properties. /// /// internal ReadOnlyPropertiesDictionary GetReadOnlyProperties() { return m_readOnlyProperties; } #endregion Internal Instance Methods } }