1 package cz.cuni.amis.pogamut.multi.utils.timekey;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Set;
9
10 import cz.cuni.amis.pogamut.multi.utils.exception.TimeKeyNotLockedException;
11 import cz.cuni.amis.utils.exception.PogamutException;
12
13
14
15
16
17
18
19 public class TimeKeyManager implements ITimeKeyManager {
20
21 private static class KeyHolder {
22
23 public long data;
24
25 public TimeKey timeKey;
26
27 public KeyHolder() {
28 this(null, 0);
29 }
30
31 public KeyHolder(long key, long data) {
32 this.timeKey = TimeKey.get(key);
33 this.data = data;
34 }
35
36 public KeyHolder(TimeKey key, long data) {
37 this.timeKey = key;
38 this.data = data;
39 }
40
41 }
42
43 private HashMap<Long, KeyHolder> locks;
44
45 private static Object instanceCreationMutex = new Object();
46 private static TimeKeyManager instance;
47
48 @Override
49 public Set<Long> getHeldKeys()
50 {
51 synchronized(locks) {
52 return Collections.unmodifiableSet( new HashSet( locks.keySet() ) );
53 }
54 }
55
56 @Override
57 public String getHeldKeysStr()
58 {
59 List<Long> keys = new ArrayList<Long>(getHeldKeys());
60 Collections.sort(keys);
61 StringBuffer sb = new StringBuffer();
62 boolean first = true;
63 for (Long key : keys) {
64 if (first) first = false;
65 else sb.append(", ");
66 sb.append(key);
67 }
68 if (sb.length() == 0) return "nothing";
69 return sb.toString();
70 }
71
72 public static TimeKeyManager get() {
73 if (instance != null) return instance;
74 synchronized(instanceCreationMutex) {
75 if (instance != null) return instance;
76 instance = new TimeKeyManager() ;
77 return instance;
78 }
79 }
80
81 @Override
82 public boolean isLocked(TimeKey key) {
83 return isLocked(key.getTime());
84 }
85
86 @Override
87 public boolean isLocked(long time) {
88 synchronized(locks) {
89 return locks.containsKey(time);
90 }
91 }
92
93 @Override
94 public void unlock(long key) throws TimeKeyNotLockedException {
95 synchronized(locks) {
96 KeyHolder n = locks.get(key);
97 if (n == null) {
98 throw new TimeKeyNotLockedException("Trying to lock an unlocked " + key);
99 }
100 if (n.data <= 0) {
101 throw new PogamutException("Locks corrupted! " + key + " locks == " + n + " <= 0, ILLEGAL!", this);
102 }
103 if (n.data == 1) {
104 locks.remove(key);
105 } else {
106 n.data -= 1;
107 }
108 }
109 }
110
111 @Override
112 public void unlockAll(long key) throws TimeKeyNotLockedException {
113 synchronized(locks) {
114 KeyHolder n = locks.get(key);
115 if (n == null) {
116 throw new TimeKeyNotLockedException("Trying to lock an unlocked " + key);
117 }
118 locks.remove(key);
119 }
120 }
121
122 @Override
123 public void lock(long key) {
124 synchronized(locks) {
125 KeyHolder n = locks.get(key);
126 if (n == null) {
127 locks.put(key, new KeyHolder(key, 1));
128 } else {
129 n.data += 1;
130 }
131 }
132 }
133
134 private TimeKeyManager() {
135 locks = new HashMap<Long, KeyHolder>();
136 }
137
138 @Override
139 public void unlockAll() {
140 synchronized(locks) {
141 while (locks.size() > 0) {
142 Long time = locks.keySet().iterator().next();
143 if (time == null) break;
144 try {
145 unlockAll(time);
146 } catch (TimeKeyNotLockedException e) {
147 }
148 }
149 }
150 }
151
152 }