@@ -95,7 +95,7 @@ protected synchronized static Map<JacobObject, String> addThread() {
95
95
}
96
96
97
97
/**
98
- * returns the pool for this thread if it exists. can create a new one if
98
+ * Returns the pool for this thread if it exists. can create a new one if
99
99
* you wish by passing in TRUE
100
100
*
101
101
* @param createIfDoesNotExist
@@ -115,19 +115,20 @@ protected synchronized static Map<JacobObject, String> getThreadObjects(
115
115
* Iterates across all of the entries in the Hashmap in the rot that
116
116
* corresponds to this thread. This calls safeRelease() on each entry and
117
117
* then clears the map when done and removes it from the rot. All traces of
118
- * this thread's objects will disapear . This is called by COMThread in the
118
+ * this thread's objects will disappear . This is called by COMThread in the
119
119
* tear down and provides a synchronous way of releasing memory
120
120
*/
121
- protected synchronized static void clearObjects () {
122
- Map <JacobObject , String > tab = getThreadObjects (false );
121
+ protected static void clearObjects () {
123
122
if (JacobObject .isDebugEnabled ()) {
124
123
JacobObject .debug ("ROT: " + rot .keySet ().size ()
125
124
+ " thread tables exist" );
126
125
}
126
+
127
+ Map <JacobObject , String > tab = getThreadObjects (false );
127
128
if (tab != null ) {
128
129
if (JacobObject .isDebugEnabled ()) {
129
130
JacobObject .debug ("ROT: " + tab .keySet ().size ()
130
- + " objects to clear in this thread " );
131
+ + " objects to clear in this thread's ROT " );
131
132
}
132
133
// walk the values
133
134
Iterator <JacobObject > it = tab .keySet ().iterator ();
@@ -155,13 +156,11 @@ protected synchronized static void clearObjects() {
155
156
}
156
157
o .safeRelease ();
157
158
}
158
- // used to be an iterator.remove() but why bother when we're
159
- // nuking them all anyway?
160
159
}
161
160
// empty the collection
162
161
tab .clear ();
163
162
// remove the collection from rot
164
- rot . remove ( Thread . currentThread (). getName () );
163
+ ROT . removeThread ( );
165
164
if (JacobObject .isDebugEnabled ()) {
166
165
JacobObject .debug ("ROT: thread table cleared and removed" );
167
166
}
@@ -172,31 +171,52 @@ protected synchronized static void clearObjects() {
172
171
}
173
172
}
174
173
174
+ /**
175
+ * Removes the map from the rot that is associated with the current thread.
176
+ */
177
+ private synchronized static void removeThread () {
178
+ // should this see if it exists first?
179
+ rot .remove (Thread .currentThread ().getName ());
180
+ }
181
+
175
182
/**
176
183
* @deprecated the java model leave the responsibility of clearing up
177
184
* objects to the Garbage Collector. Our programming model
178
185
* should not require that the user specifically remove object
179
- * from the thread.
180
- *
181
- * This will remove an object from the ROT
186
+ * from the thread. <br>
187
+ * This will remove an object from the ROT <br>
188
+ * This does not need to be synchronized because only the rot
189
+ * modification related methods need to synchronized. Each
190
+ * individual map is only modified in a single thread.
182
191
* @param o
183
192
*/
184
193
@ Deprecated
185
- protected synchronized static void removeObject (JacobObject o ) {
186
- String t_name = Thread .currentThread ().getName ();
187
- Map <JacobObject , String > tab = rot .get (t_name );
194
+ protected static void removeObject (JacobObject o ) {
195
+ Map <JacobObject , String > tab = ROT .getThreadObjects (false );
188
196
if (tab != null ) {
189
197
tab .remove (o );
190
198
}
191
199
o .safeRelease ();
192
200
}
193
201
194
202
/**
195
- * adds an object to the HashMap for the current thread
203
+ * Adds an object to the HashMap for the current thread. <br>
204
+ * <p>
205
+ * This method does not need to be threaded because the only concurrent
206
+ * modification risk is on the hash map that contains all of the thread
207
+ * related hash maps. The individual thread related maps are only used on a
208
+ * per thread basis so there isn't a locking issue.
209
+ * <p>
210
+ * In addition, this method cannot be threaded because it calls
211
+ * ComThread.InitMTA. The ComThread object has some methods that call ROT so
212
+ * we could end up deadlocked. This method should be safe without the
213
+ * synchronization because the ROT works on per thread basis and the methods
214
+ * that add threads and remove thread related entries are all synchronized
215
+ *
196
216
*
197
217
* @param o
198
218
*/
199
- protected synchronized static void addObject (JacobObject o ) {
219
+ protected static void addObject (JacobObject o ) {
200
220
// check the system property to see if this class is put in the ROT
201
221
// the default value is "true" which simulates the old behavior
202
222
String shouldIncludeClassInROT = System .getProperty (o .getClass ()
@@ -208,18 +228,22 @@ protected synchronized static void addObject(JacobObject o) {
208
228
+ o .getClass ().getName () + " not added to ROT" );
209
229
}
210
230
} else {
231
+ // first see if we have a table for this thread
211
232
Map <JacobObject , String > tab = getThreadObjects (false );
212
233
if (tab == null ) {
213
234
// this thread has not been initialized as a COM thread
214
235
// so make it part of MTA for backwards compatibility
215
236
ComThread .InitMTA (false );
237
+ // don't really need the "true" because the InitMTA will have
238
+ // called back to the ROT to create a table for this thread
216
239
tab = getThreadObjects (true );
217
240
}
218
241
if (JacobObject .isDebugEnabled ()) {
219
242
JacobObject .debug ("ROT: adding " + o + "->"
220
243
+ o .getClass ().getName ()
221
244
+ " table size prior to addition:" + tab .size ());
222
245
}
246
+ // add the object to the table that is specific to this thread
223
247
if (tab != null ) {
224
248
tab .put (o , null );
225
249
}
0 commit comments