diff options
author | onefang | 2019-05-19 21:24:15 +1000 |
---|---|---|
committer | onefang | 2019-05-19 21:24:15 +1000 |
commit | 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch) | |
tree | a9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Framework/TaskInventoryDictionary.cs | |
parent | Add a build script. (diff) | |
download | opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2 opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz |
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to 'OpenSim/Framework/TaskInventoryDictionary.cs')
-rw-r--r-- | OpenSim/Framework/TaskInventoryDictionary.cs | 196 |
1 files changed, 190 insertions, 6 deletions
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 8af2c41..223d91f 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs | |||
@@ -27,9 +27,13 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Threading; | ||
31 | using System.Reflection; | ||
30 | using System.Xml; | 32 | using System.Xml; |
33 | using System.Diagnostics; | ||
31 | using System.Xml.Schema; | 34 | using System.Xml.Schema; |
32 | using System.Xml.Serialization; | 35 | using System.Xml.Serialization; |
36 | using log4net; | ||
33 | using OpenMetaverse; | 37 | using OpenMetaverse; |
34 | 38 | ||
35 | namespace OpenSim.Framework | 39 | namespace OpenSim.Framework |
@@ -47,6 +51,187 @@ namespace OpenSim.Framework | |||
47 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 51 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
48 | 52 | ||
49 | private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); | 53 | private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); |
54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
55 | |||
56 | private Thread LockedByThread; | ||
57 | // private string WriterStack; | ||
58 | |||
59 | // private Dictionary<Thread, string> ReadLockers = | ||
60 | // new Dictionary<Thread, string>(); | ||
61 | |||
62 | /// <value> | ||
63 | /// An advanced lock for inventory data | ||
64 | /// </value> | ||
65 | private volatile System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
66 | |||
67 | |||
68 | ~TaskInventoryDictionary() | ||
69 | { | ||
70 | m_itemLock.Dispose(); | ||
71 | m_itemLock = null; | ||
72 | } | ||
73 | |||
74 | /// <summary> | ||
75 | /// Are we readlocked by the calling thread? | ||
76 | /// </summary> | ||
77 | public bool IsReadLockedByMe() | ||
78 | { | ||
79 | if (m_itemLock.RecursiveReadCount > 0) | ||
80 | { | ||
81 | return true; | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | return false; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | /// <summary> | ||
90 | /// Lock our inventory list for reading (many can read, one can write) | ||
91 | /// </summary> | ||
92 | public void LockItemsForRead(bool locked) | ||
93 | { | ||
94 | if (locked) | ||
95 | { | ||
96 | if (m_itemLock.IsWriteLockHeld && LockedByThread != null) | ||
97 | { | ||
98 | if (!LockedByThread.IsAlive) | ||
99 | { | ||
100 | //Locked by dead thread, reset. | ||
101 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | if (m_itemLock.RecursiveReadCount > 0) | ||
106 | { | ||
107 | m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
108 | try | ||
109 | { | ||
110 | // That call stack is useful for end users only. RealProgrammers need a full dump. Commented. | ||
111 | // StackTrace stackTrace = new StackTrace(); // get call stack | ||
112 | // StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) | ||
113 | // | ||
114 | // // write call stack method names | ||
115 | // foreach (StackFrame stackFrame in stackFrames) | ||
116 | // { | ||
117 | // m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name | ||
118 | // } | ||
119 | |||
120 | // The below is far more useful | ||
121 | // System.Console.WriteLine("------------------------------------------"); | ||
122 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
123 | // System.Console.WriteLine("------------------------------------------"); | ||
124 | // foreach (KeyValuePair<Thread, string> kvp in ReadLockers) | ||
125 | // { | ||
126 | // System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name); | ||
127 | // System.Console.WriteLine("------------------------------------------"); | ||
128 | // } | ||
129 | } | ||
130 | catch | ||
131 | {} | ||
132 | m_itemLock.ExitReadLock(); | ||
133 | } | ||
134 | if (m_itemLock.RecursiveWriteCount > 0) | ||
135 | { | ||
136 | m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
137 | // try | ||
138 | // { | ||
139 | // System.Console.WriteLine("------------------------------------------"); | ||
140 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
141 | // System.Console.WriteLine("------------------------------------------"); | ||
142 | // System.Console.WriteLine("Locker's call stack:\n" + WriterStack); | ||
143 | // System.Console.WriteLine("------------------------------------------"); | ||
144 | // } | ||
145 | // catch | ||
146 | // {} | ||
147 | m_itemLock.ExitWriteLock(); | ||
148 | } | ||
149 | |||
150 | while (!m_itemLock.TryEnterReadLock(60000)) | ||
151 | { | ||
152 | m_log.Error("Thread lock detected while trying to aquire READ lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
153 | //if (m_itemLock.IsWriteLockHeld) | ||
154 | //{ | ||
155 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
156 | // System.Console.WriteLine("------------------------------------------"); | ||
157 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
158 | // System.Console.WriteLine("------------------------------------------"); | ||
159 | // System.Console.WriteLine("Locker's call stack:\n" + WriterStack); | ||
160 | // System.Console.WriteLine("------------------------------------------"); | ||
161 | // LockedByThread = null; | ||
162 | // ReadLockers.Clear(); | ||
163 | //} | ||
164 | } | ||
165 | // ReadLockers[Thread.CurrentThread] = Environment.StackTrace; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | if (m_itemLock.RecursiveReadCount>0) | ||
170 | { | ||
171 | m_itemLock.ExitReadLock(); | ||
172 | } | ||
173 | // if (m_itemLock.RecursiveReadCount == 0) | ||
174 | // ReadLockers.Remove(Thread.CurrentThread); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /// <summary> | ||
179 | /// Lock our inventory list for writing (many can read, one can write) | ||
180 | /// </summary> | ||
181 | public void LockItemsForWrite(bool locked) | ||
182 | { | ||
183 | if (locked) | ||
184 | { | ||
185 | //Enter a write lock, wait indefinately for one to open. | ||
186 | if (m_itemLock.RecursiveReadCount > 0) | ||
187 | { | ||
188 | m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
189 | m_itemLock.ExitReadLock(); | ||
190 | } | ||
191 | if (m_itemLock.RecursiveWriteCount > 0) | ||
192 | { | ||
193 | m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
194 | |||
195 | m_itemLock.ExitWriteLock(); | ||
196 | } | ||
197 | while (!m_itemLock.TryEnterWriteLock(60000)) | ||
198 | { | ||
199 | if (m_itemLock.IsWriteLockHeld) | ||
200 | { | ||
201 | m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
202 | // System.Console.WriteLine("------------------------------------------"); | ||
203 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
204 | // System.Console.WriteLine("------------------------------------------"); | ||
205 | // System.Console.WriteLine("Locker's call stack:\n" + WriterStack); | ||
206 | // System.Console.WriteLine("------------------------------------------"); | ||
207 | } | ||
208 | else | ||
209 | { | ||
210 | m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by a reader. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
211 | // System.Console.WriteLine("------------------------------------------"); | ||
212 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
213 | // System.Console.WriteLine("------------------------------------------"); | ||
214 | // foreach (KeyValuePair<Thread, string> kvp in ReadLockers) | ||
215 | // { | ||
216 | // System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name); | ||
217 | // System.Console.WriteLine("------------------------------------------"); | ||
218 | // } | ||
219 | } | ||
220 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
221 | // ReadLockers.Clear(); | ||
222 | } | ||
223 | |||
224 | LockedByThread = Thread.CurrentThread; | ||
225 | // WriterStack = Environment.StackTrace; | ||
226 | } | ||
227 | else | ||
228 | { | ||
229 | if (m_itemLock.RecursiveWriteCount > 0) | ||
230 | { | ||
231 | m_itemLock.ExitWriteLock(); | ||
232 | } | ||
233 | } | ||
234 | } | ||
50 | 235 | ||
51 | #region ICloneable Members | 236 | #region ICloneable Members |
52 | 237 | ||
@@ -54,14 +239,13 @@ namespace OpenSim.Framework | |||
54 | { | 239 | { |
55 | TaskInventoryDictionary clone = new TaskInventoryDictionary(); | 240 | TaskInventoryDictionary clone = new TaskInventoryDictionary(); |
56 | 241 | ||
57 | lock (this) | 242 | m_itemLock.EnterReadLock(); |
243 | foreach (UUID uuid in Keys) | ||
58 | { | 244 | { |
59 | foreach (UUID uuid in Keys) | 245 | clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); |
60 | { | ||
61 | clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); | ||
62 | } | ||
63 | } | 246 | } |
64 | 247 | m_itemLock.ExitReadLock(); | |
248 | |||
65 | return clone; | 249 | return clone; |
66 | } | 250 | } |
67 | 251 | ||