diff options
author | MW | 2008-02-14 18:59:03 +0000 |
---|---|---|
committer | MW | 2008-02-14 18:59:03 +0000 |
commit | 8ad450f83e70a45b79d9b058bf46854c7168a69c (patch) | |
tree | 3da8f1a76a56830250f63fc77b21dc55055b86a9 /OpenSim/Region | |
parent | * Fixed accessibility problem on ITerrainChannel (diff) | |
download | opensim-SC_OLD-8ad450f83e70a45b79d9b058bf46854c7168a69c.zip opensim-SC_OLD-8ad450f83e70a45b79d9b058bf46854c7168a69c.tar.gz opensim-SC_OLD-8ad450f83e70a45b79d9b058bf46854c7168a69c.tar.bz2 opensim-SC_OLD-8ad450f83e70a45b79d9b058bf46854c7168a69c.tar.xz |
More work on trying to get AvatarFactoryModule to play nicely with multiple threads
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs | 143 |
1 files changed, 80 insertions, 63 deletions
diff --git a/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs b/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs index 7933593..f43657c 100644 --- a/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs +++ b/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs | |||
@@ -57,34 +57,27 @@ namespace OpenSim.Region.Environment.Modules | |||
57 | 57 | ||
58 | public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance) | 58 | public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance) |
59 | { | 59 | { |
60 | appearance = CheckCache(avatarId); | 60 | |
61 | if (appearance != null) | ||
62 | { | ||
63 | return true; | ||
64 | } | ||
65 | |||
66 | //not in cache so check to see if another thread is already fetching it | ||
67 | //should only let one thread at a time do this part | 61 | //should only let one thread at a time do this part |
68 | EventWaitHandle waitHandle = null; | 62 | EventWaitHandle waitHandle = null; |
63 | bool fetchInProgress = false; | ||
69 | lock (m_syncLock) | 64 | lock (m_syncLock) |
70 | { | 65 | { |
66 | appearance = CheckCache(avatarId); | ||
67 | if (appearance != null) | ||
68 | { | ||
69 | return true; | ||
70 | } | ||
71 | |||
72 | //not in cache so check to see if another thread is already fetching it | ||
71 | if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle)) | 73 | if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle)) |
72 | { | 74 | { |
73 | waitHandle.WaitOne(); | 75 | fetchInProgress = true; |
74 | appearance = CheckCache(avatarId); | ||
75 | if (appearance != null) | ||
76 | { | ||
77 | waitHandle = null; | ||
78 | return true; | ||
79 | } | ||
80 | else | ||
81 | { | ||
82 | waitHandle = null; | ||
83 | return false; | ||
84 | } | ||
85 | } | 76 | } |
86 | else | 77 | else |
87 | { | 78 | { |
79 | fetchInProgress = false; | ||
80 | |||
88 | //no thread already fetching this appearance, so add a wait handle to list | 81 | //no thread already fetching this appearance, so add a wait handle to list |
89 | //for any following threads that want the same appearance | 82 | //for any following threads that want the same appearance |
90 | waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); | 83 | waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); |
@@ -92,62 +85,84 @@ namespace OpenSim.Region.Environment.Modules | |||
92 | } | 85 | } |
93 | } | 86 | } |
94 | 87 | ||
95 | 88 | if (fetchInProgress) | |
96 | //this is the first thread to request this appearance | ||
97 | //so let it check the db and if not found then create a default appearance | ||
98 | //and add that to the cache | ||
99 | appearance = CheckDatabase(avatarId); | ||
100 | if (appearance != null) | ||
101 | { | 89 | { |
102 | //appearance has now been added to cache so lets pulse any waiting threads | 90 | waitHandle.WaitOne(); |
103 | lock (m_syncLock) | 91 | appearance = CheckCache(avatarId); |
92 | if (appearance != null) | ||
104 | { | 93 | { |
105 | m_fetchesInProgress.Remove(avatarId); | 94 | waitHandle = null; |
106 | waitHandle.Set(); | 95 | return true; |
107 | } | 96 | } |
108 | waitHandle = null; | 97 | else |
109 | return true; | ||
110 | } | ||
111 | |||
112 | //not found a appearance for the user, so create a new default one | ||
113 | appearance = CreateDefault(avatarId); | ||
114 | if (appearance != null) | ||
115 | { | ||
116 | //update database | ||
117 | if (m_enablePersist) | ||
118 | { | 98 | { |
119 | m_appearanceMapper.Add(avatarId.UUID, appearance); | 99 | waitHandle = null; |
100 | return false; | ||
120 | } | 101 | } |
121 | 102 | ||
122 | //add appearance to dictionary cache | 103 | } |
123 | lock (m_avatarsAppearance) | 104 | else |
105 | { | ||
106 | Thread.Sleep(5000); | ||
107 | |||
108 | //this is the first thread to request this appearance | ||
109 | //so let it check the db and if not found then create a default appearance | ||
110 | //and add that to the cache | ||
111 | appearance = CheckDatabase(avatarId); | ||
112 | if (appearance != null) | ||
124 | { | 113 | { |
125 | m_avatarsAppearance[avatarId] = appearance; | 114 | //appearance has now been added to cache so lets pulse any waiting threads |
115 | lock (m_syncLock) | ||
116 | { | ||
117 | m_fetchesInProgress.Remove(avatarId); | ||
118 | waitHandle.Set(); | ||
119 | } | ||
120 | // waitHandle.Close(); | ||
121 | waitHandle = null; | ||
122 | return true; | ||
126 | } | 123 | } |
127 | 124 | ||
128 | //appearance has now been added to cache so lets pulse any waiting threads | 125 | //not found a appearance for the user, so create a new default one |
129 | lock (m_syncLock) | 126 | appearance = CreateDefault(avatarId); |
127 | if (appearance != null) | ||
130 | { | 128 | { |
131 | m_fetchesInProgress.Remove(avatarId); | 129 | //update database |
132 | waitHandle.Set(); | 130 | if (m_enablePersist) |
131 | { | ||
132 | m_appearanceMapper.Add(avatarId.UUID, appearance); | ||
133 | } | ||
134 | |||
135 | //add appearance to dictionary cache | ||
136 | lock (m_avatarsAppearance) | ||
137 | { | ||
138 | m_avatarsAppearance[avatarId] = appearance; | ||
139 | } | ||
140 | |||
141 | //appearance has now been added to cache so lets pulse any waiting threads | ||
142 | lock (m_syncLock) | ||
143 | { | ||
144 | m_fetchesInProgress.Remove(avatarId); | ||
145 | waitHandle.Set(); | ||
146 | } | ||
147 | // waitHandle.Close(); | ||
148 | waitHandle = null; | ||
149 | return true; | ||
133 | } | 150 | } |
134 | waitHandle = null; | 151 | else |
135 | return true; | ||
136 | } | ||
137 | else | ||
138 | { | ||
139 | //something went wrong, so release the wait handle and remove it | ||
140 | //all waiting threads will fail to find cached appearance | ||
141 | //but its better for them to fail than wait for ever | ||
142 | lock (m_syncLock) | ||
143 | { | 152 | { |
144 | m_fetchesInProgress.Remove(avatarId); | 153 | //something went wrong, so release the wait handle and remove it |
145 | waitHandle.Set(); | 154 | //all waiting threads will fail to find cached appearance |
155 | //but its better for them to fail than wait for ever | ||
156 | lock (m_syncLock) | ||
157 | { | ||
158 | m_fetchesInProgress.Remove(avatarId); | ||
159 | waitHandle.Set(); | ||
160 | } | ||
161 | //waitHandle.Close(); | ||
162 | waitHandle = null; | ||
163 | return false; | ||
146 | } | 164 | } |
147 | waitHandle = null; | ||
148 | return false; | ||
149 | } | 165 | } |
150 | |||
151 | } | 166 | } |
152 | 167 | ||
153 | private AvatarAppearance CreateDefault(LLUUID avatarId) | 168 | private AvatarAppearance CreateDefault(LLUUID avatarId) |
@@ -197,8 +212,10 @@ namespace OpenSim.Region.Environment.Modules | |||
197 | 212 | ||
198 | public void Initialise(Scene scene, IConfigSource source) | 213 | public void Initialise(Scene scene, IConfigSource source) |
199 | { | 214 | { |
200 | scene.RegisterModuleInterface<IAvatarFactory>(this); | 215 | |
201 | scene.EventManager.OnNewClient += NewClient; | 216 | scene.RegisterModuleInterface<IAvatarFactory>(this); |
217 | scene.EventManager.OnNewClient += NewClient; | ||
218 | |||
202 | 219 | ||
203 | if (m_scene == null) | 220 | if (m_scene == null) |
204 | { | 221 | { |