comparison gnv-artifacts/src/main/java/de/intevation/gnv/utils/ExclusiveExec.java @ 1119:7c4f81f74c47

merged gnv-artifacts
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:00 +0200
parents f953c9a559d8
children
comparison
equal deleted inserted replaced
1027:fca4b5eb8d2f 1119:7c4f81f74c47
1 /*
2 * Copyright (c) 2010 by Intevation GmbH
3 *
4 * This program is free software under the LGPL (>=v2.1)
5 * Read the file LGPL.txt coming with the software for details
6 * or visit http://www.gnu.org/licenses/ if it does not exist.
7 */
8
9 package de.intevation.gnv.utils;
10
11 import java.util.HashMap;
12
13 /**
14 * This class can be used to synchronize threads with a given key. To use this
15 * synchronization, you first need to do call {@link #acquire(java.lang.Object)}
16 * to retrieve a {@link UniqueKey}. After this, you can call the code being
17 * synchronized. After this execution, you need to call
18 * {@link #release(UniqueKey)} with your token you retrieved from {@link
19 * #acquire(java.lang.Object)}. A thread needs to wait for another thread if their keys
20 * are equal. Threads with different keys don't need to wait for each other.
21 *
22 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
23 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
24 */
25 public final class ExclusiveExec
26 {
27 /**
28 * The only instance of this singleton.
29 */
30 public static final ExclusiveExec INSTANCE = new ExclusiveExec();
31
32 private HashMap tokens;
33
34 /**
35 * This class represents a unique key with a reference counter.
36 */
37 public static class UniqueKey {
38 Object key;
39 int [] refs;
40
41 /**
42 * Constructs a new UniqueKey.
43 *
44 * @param key The key of this unique key.
45 */
46 public UniqueKey(Object key) {
47 this.key = key;
48 refs = new int[1];
49 }
50 }
51
52 /**
53 * Private constructor. Use {@link #INSTANCE} instead.
54 */
55 private ExclusiveExec() {
56 tokens = new HashMap();
57 }
58
59 /**
60 * This method serves a {@link UniqueKey} and starts a synchronized code
61 * block.
62 *
63 * @param key The key used to identify same threads.
64 * @return UniqueKey. Use this object to call {@link #release(UniqueKey)}
65 * at the end of your code being synchronized.
66 */
67 public UniqueKey acquire(Object key) {
68
69 try {
70 UniqueKey internalKey = null;
71 synchronized (tokens) {
72 internalKey = (UniqueKey)tokens.get(key);
73
74 if (internalKey == null) {
75 tokens.put(key, internalKey = new UniqueKey(key));
76 }
77 }
78
79 synchronized (internalKey) {
80 ++internalKey.refs[0];
81 while (internalKey.refs[0] > 1) {
82 internalKey.wait(10000L);
83 }
84 }
85
86 return internalKey;
87 }
88 catch (InterruptedException ie) {
89 return null;
90 }
91 }
92
93 /**
94 * This method releases a lock. Call this method at the end of your code
95 * being synchronized.
96 *
97 * @param internalKey Token retrieved by {@link #acquire(Object)}.
98 */
99 public void release(UniqueKey internalKey) {
100 if (internalKey != null) {
101 synchronized (internalKey) {
102 if (--internalKey.refs[0] < 1) {
103 synchronized (tokens) {
104 tokens.remove(internalKey.key);
105 }
106 }
107 internalKey.notifyAll();
108 }
109 }
110 }
111 }
112 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org