comparison gnv-artifacts/src/main/java/de/intevation/gnv/utils/ExclusiveExec.java @ 775:eedad2ddad14

Removed race-condition while shapefile creation (issue164). gnv-artifacts/trunk@841 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Fri, 26 Mar 2010 15:20:32 +0000
parents
children 9a828e5a2390
comparison
equal deleted inserted replaced
774:d0a39efbfd96 775:eedad2ddad14
1 package de.intevation.gnv.utils;
2
3 import java.util.HashMap;
4
5 /**
6 * This class can be used to synchronize threads with a given key. To use this
7 * synchronization, you first need to do call {@link #acquire(String)} to
8 * retrieve a {@link UniqueKey}. After this, you can call the code being
9 * synchronized. After this execution, you need to call
10 * {@link #release(UniqueKey)} with your token you retrieved from {@link
11 * #acquire(String)}. A thread needs to wait for another thread if their keys
12 * are equal. Threads with different keys don't need to wait for each other.
13 *
14 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
15 * @author Ingo Weinzierl (ingo.weinzierl@intevation.de)
16 */
17 public final class ExclusiveExec
18 {
19 public static final ExclusiveExec INSTANCE = new ExclusiveExec();
20
21 private HashMap tokens;
22
23 public static class UniqueKey {
24 Object key;
25 int [] refs;
26 public UniqueKey(Object key) {
27 this.key = key;
28 refs = new int[1];
29 }
30 }
31
32 /**
33 * Private constructor. Use {@link #INSTANCE} instead.
34 */
35 private ExclusiveExec() {
36 tokens = new HashMap();
37 }
38
39 /**
40 * This method serves a {@link UniqueKey} and starts a synchronized code
41 * block.
42 *
43 * @param key The key used to identify same threads.
44 *
45 * @return UniqueKey. Use this object to call {@link #release(UniqueKey)}
46 * at the end of your code being synchronized.
47 */
48 public UniqueKey acquire(Object key) {
49
50 try {
51 UniqueKey internalKey = null;
52 synchronized (tokens) {
53 internalKey = (UniqueKey)tokens.get(key);
54
55 if (internalKey == null) {
56 tokens.put(key, internalKey = new UniqueKey(key));
57 }
58 }
59
60 synchronized (internalKey) {
61 ++internalKey.refs[0];
62 while (internalKey.refs[0] > 1) {
63 internalKey.wait(10000L);
64 }
65 }
66
67 return internalKey;
68 }
69 catch (InterruptedException ie) {
70 return null;
71 }
72 }
73
74 /**
75 * This method releases a lock. Call this method at the end of your code
76 * being synchronized.
77 *
78 * @param internalKey Token retrieved by {@link #acquire(Object)}.
79 */
80 public void release(UniqueKey internalKey) {
81 if (internalKey != null) {
82 synchronized (internalKey) {
83 if (--internalKey.refs[0] < 1) {
84 synchronized (tokens) {
85 tokens.remove(internalKey.key);
86 }
87 }
88 internalKey.notifyAll();
89 }
90 }
91 }
92 }
93 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org