jt
2021-06-10 5d0d028456874576560552f5a5c4e8b801786f11
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#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
{
    /// <summary>
    /// Implementation of Properties collection for the <see cref="log4net.GlobalContext"/>
    /// </summary>
    /// <remarks>
    /// <para>
    /// 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.
    /// </para>
    /// <para>
    /// This class is optimized to the scenario where the properties are read frequently
    /// and are modified infrequently.
    /// </para>
    /// </remarks>
    /// <author>Nicko Cadell</author>
    public sealed class GlobalContextProperties : ContextPropertiesBase
    {
        #region Private Instance Fields
 
        /// <summary>
        /// The read only copy of the properties.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This variable is declared <c>volatile</c> to prevent the compiler and JIT from
        /// reordering reads and writes of this thread performed on different threads.
        /// </para>
        /// </remarks>
#if NETCF
        private ReadOnlyPropertiesDictionary m_readOnlyProperties = new ReadOnlyPropertiesDictionary();
#else
        private volatile ReadOnlyPropertiesDictionary m_readOnlyProperties = new ReadOnlyPropertiesDictionary();
#endif
 
        /// <summary>
        /// Lock object used to synchronize updates within this instance
        /// </summary>
        private readonly object m_syncRoot = new object();
 
        #endregion Private Instance Fields
 
        #region Public Instance Constructors
 
        /// <summary>
        /// Constructor
        /// </summary>
        /// <remarks>
        /// <para>
        /// Initializes a new instance of the <see cref="GlobalContextProperties" /> class.
        /// </para>
        /// </remarks>
        internal GlobalContextProperties()
        {
        }
 
        #endregion Public Instance Constructors
 
        #region Public Instance Properties
 
        /// <summary>
        /// Gets or sets the value of a property
        /// </summary>
        /// <value>
        /// The value for the property with the specified key
        /// </value>
        /// <remarks>
        /// <para>
        /// 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.
        /// </para>
        /// </remarks>
        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
 
        /// <summary>
        /// Remove a property from the global context
        /// </summary>
        /// <param name="key">the key for the entry to remove</param>
        /// <remarks>
        /// <para>
        /// Removing an entry from the global context properties is relatively expensive compared
        /// with reading a value. 
        /// </para>
        /// </remarks>
        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);
                }
            }
        }
 
        /// <summary>
        /// Clear the global context properties
        /// </summary>
        public void Clear()
        {
            lock(m_syncRoot)
            {
                m_readOnlyProperties = new ReadOnlyPropertiesDictionary();
            }
        }
 
        #endregion Public Instance Methods
 
        #region Internal Instance Methods
 
        /// <summary>
        /// Get a readonly immutable copy of the properties
        /// </summary>
        /// <returns>the current global context properties</returns>
        /// <remarks>
        /// <para>
        /// This implementation is fast because the GlobalContextProperties class
        /// stores a readonly copy of the properties.
        /// </para>
        /// </remarks>
        internal ReadOnlyPropertiesDictionary GetReadOnlyProperties()
        {
            return m_readOnlyProperties;
        }
 
        #endregion Internal Instance Methods
    }
}