aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/TaskInventoryDictionary.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/TaskInventoryDictionary.cs')
-rw-r--r--OpenSim/Framework/TaskInventoryDictionary.cs131
1 files changed, 126 insertions, 5 deletions
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs
index 25ae6b0..a8a53f2 100644
--- a/OpenSim/Framework/TaskInventoryDictionary.cs
+++ b/OpenSim/Framework/TaskInventoryDictionary.cs
@@ -27,9 +27,13 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Threading;
31using System.Reflection;
30using System.Xml; 32using System.Xml;
33using System.Diagnostics;
31using System.Xml.Schema; 34using System.Xml.Schema;
32using System.Xml.Serialization; 35using System.Xml.Serialization;
36using log4net;
33using OpenMetaverse; 37using OpenMetaverse;
34 38
35namespace OpenSim.Framework 39namespace OpenSim.Framework
@@ -45,6 +49,124 @@ namespace OpenSim.Framework
45 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 50
47 private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); 51 private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem));
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private Thread LockedByThread;
55 /// <value>
56 /// An advanced lock for inventory data
57 /// </value>
58 private System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim();
59
60 /// <summary>
61 /// Are we readlocked by the calling thread?
62 /// </summary>
63 public bool IsReadLockedByMe()
64 {
65 if (m_itemLock.RecursiveReadCount > 0)
66 {
67 return true;
68 }
69 else
70 {
71 return false;
72 }
73 }
74
75 /// <summary>
76 /// Lock our inventory list for reading (many can read, one can write)
77 /// </summary>
78 public void LockItemsForRead(bool locked)
79 {
80 if (locked)
81 {
82 if (m_itemLock.IsWriteLockHeld && LockedByThread != null)
83 {
84 if (!LockedByThread.IsAlive)
85 {
86 //Locked by dead thread, reset.
87 m_itemLock = new System.Threading.ReaderWriterLockSlim();
88 }
89 }
90
91 if (m_itemLock.RecursiveReadCount > 0)
92 {
93 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.");
94 try
95 {
96 StackTrace stackTrace = new StackTrace(); // get call stack
97 StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
98
99 // write call stack method names
100 foreach (StackFrame stackFrame in stackFrames)
101 {
102 m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name
103 }
104 }
105 catch
106 {}
107 m_itemLock.ExitReadLock();
108 }
109 if (m_itemLock.RecursiveWriteCount > 0)
110 {
111 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
112 m_itemLock.ExitWriteLock();
113 }
114
115 while (!m_itemLock.TryEnterReadLock(60000))
116 {
117 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.");
118 if (m_itemLock.IsWriteLockHeld)
119 {
120 m_itemLock = new System.Threading.ReaderWriterLockSlim();
121 }
122 }
123 }
124 else
125 {
126 if (m_itemLock.RecursiveReadCount>0)
127 {
128 m_itemLock.ExitReadLock();
129 }
130 }
131 }
132
133 /// <summary>
134 /// Lock our inventory list for writing (many can read, one can write)
135 /// </summary>
136 public void LockItemsForWrite(bool locked)
137 {
138 if (locked)
139 {
140 //Enter a write lock, wait indefinately for one to open.
141 if (m_itemLock.RecursiveReadCount > 0)
142 {
143 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.");
144 m_itemLock.ExitReadLock();
145 }
146 if (m_itemLock.RecursiveWriteCount > 0)
147 {
148 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
149 m_itemLock.ExitWriteLock();
150 }
151 while (!m_itemLock.TryEnterWriteLock(60000))
152 {
153 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.");
154 if (m_itemLock.IsWriteLockHeld)
155 {
156 m_itemLock = new System.Threading.ReaderWriterLockSlim();
157 }
158 }
159
160 LockedByThread = Thread.CurrentThread;
161 }
162 else
163 {
164 if (m_itemLock.RecursiveWriteCount > 0)
165 {
166 m_itemLock.ExitWriteLock();
167 }
168 }
169 }
48 170
49 #region ICloneable Members 171 #region ICloneable Members
50 172
@@ -52,13 +174,12 @@ namespace OpenSim.Framework
52 { 174 {
53 TaskInventoryDictionary clone = new TaskInventoryDictionary(); 175 TaskInventoryDictionary clone = new TaskInventoryDictionary();
54 176
55 lock (this) 177 m_itemLock.EnterReadLock();
178 foreach (UUID uuid in Keys)
56 { 179 {
57 foreach (UUID uuid in Keys) 180 clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone());
58 {
59 clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone());
60 }
61 } 181 }
182 m_itemLock.ExitReadLock();
62 183
63 return clone; 184 return clone;
64 } 185 }