Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

Coordinator.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. package coordination;
  2. import java.util.*; //!!!
  3. /**
  4. * The Coordinator class provides the basic functionality for synchronizing
  5. * and coordinating different threads upon entering and exiting methods.
  6. * It can be used in two different ways:
  7. * 1) by instantiating regular coordinator objects that are used by aspects; or
  8. * 2) by extending it (sub-classing) with coordinator aspects.
  9. * <P>
  10. * Method invocations are the smallest units for defining critical sections
  11. * and pre-conditions. The use of coordinators, either regular objects or aspect
  12. * instances, should always end up by invoking guardedEntry(...) in a
  13. * before weave and guardedExit(...) in an after weave for all methods that
  14. * need coordination. guardedEntry and guardedExit are the methods that
  15. * actually manage the synchronization and coordination constraints given
  16. * by their parameters and by pre-existent exclusion markers.
  17. * <P>
  18. * The synchronization of threads for the execution of critical section
  19. * methods in an object is done by marking those methods as self- and/or
  20. * mutually-exclusive (addSelfex, addMutex).
  21. * Just by itself, addSelfex("M") does not enforce the self-exclusion
  22. * of method M - enforcement is done by invoking guardedEntry before
  23. * M is executed. Similarly, addMutex(new String[] {"M1", "M2"}) does
  24. * not enforce the mutual exclusion between methods M1 and M2.
  25. * <P>
  26. * A guardedEntry on a method that has been marked as self-exclusive
  27. * ensures that the method is executed in the invoked object by only one thread
  28. * at a time. A guardedEntry on a method that has been marked has mutually-
  29. * exclusive with other methods ensures that the execution of that method
  30. * by a thread in the invoked object temporarily blocks the execution by
  31. * other threads of the methods that are in the same mutex set.
  32. * <P>
  33. * The coordination of threads, i.e. their explicit suspension and
  34. * resumption, is done through the use of pre-conditions and coordination
  35. * actions that are passed as parameters to guardedEntry and guardedExit
  36. * with the form of anonymous classes.
  37. */
  38. public abstract aspect Coordinator {
  39. private Hashtable methods = null;
  40. private Vector exclusions = null;
  41. abstract protected pointcut synchronizationPoint();
  42. public Coordinator() {
  43. methods = new Hashtable();
  44. exclusions = new Vector(5);
  45. }
  46. before (): synchronizationPoint() {
  47. this.guardedEntry(thisJoinPointStaticPart.getSignature().getName());
  48. }
  49. after (): synchronizationPoint() {
  50. this.guardedExit(thisJoinPointStaticPart.getSignature().getName());
  51. }
  52. /**
  53. * Takes a multi-part method name (eg "BoundedBuffer.put")
  54. * and marks that method as self-exclusive.
  55. * No checks are made with respect to the existence of the method
  56. * whose name is given.
  57. */
  58. public synchronized void addSelfex(String methName) {
  59. Selfex sex = new Selfex (methName);
  60. // update db of all exclusions in this coordinator
  61. exclusions.addElement(sex);
  62. // update local info in method
  63. Method aMeth = getOrSetMethod(methName);
  64. aMeth.addExclusion(sex);
  65. }
  66. /**
  67. * Takes a multi-part method name (e.g. "BoundedBuffer.put")
  68. * and removes that method from the list of self-exclusive methods.
  69. */
  70. public synchronized void removeSelfex(String methName) {
  71. for (int i = 0; i < exclusions.size(); i++) {
  72. Exclusion sex = (Exclusion)exclusions.elementAt(i);
  73. if ((sex instanceof Selfex) &&
  74. (((Selfex)sex).methodName.equals(methName))) {
  75. // update db of all exclusions in this coordinator
  76. exclusions.removeElementAt(i);
  77. // update local info in method
  78. Method aMeth = getOrSetMethod(methName);
  79. aMeth.removeExclusion(sex);
  80. }
  81. }
  82. }
  83. /**
  84. * Takes an array of multi-part method names and marks those
  85. * methods as mutually exclusive.
  86. * No checks are made with respect to the existence of the methods
  87. * whose names are given.
  88. */
  89. public synchronized void addMutex(String[] methNames) {
  90. Mutex mux = new Mutex(methNames);
  91. // update db of all exclusions in this coordinator
  92. exclusions.addElement(mux);
  93. // update local info in each method
  94. for (int i = 0; i < methNames.length; i++) {
  95. Method aMeth = getOrSetMethod(methNames[i]);
  96. aMeth.addExclusion(mux);
  97. }
  98. }
  99. /**
  100. * Takes an array of multi-part method names that correspond
  101. * to an existing mutex set and remove the mutual exclusion constraint.
  102. * If the given mutex set does not exist, removeMutex does nothing.
  103. */
  104. public synchronized void removeMutex(String[] methNames) {
  105. for (int i = 0; i < exclusions.size(); i++) {
  106. Exclusion mux = (Exclusion)exclusions.elementAt(i);
  107. if (mux instanceof Mutex) {
  108. boolean same = true;
  109. for (int j = 0; j < methNames.length; j++)
  110. if (!methNames[j].equals(((Mutex)mux).methodNames[j]))
  111. same = false;
  112. if (same) {
  113. // update db of all exclusions in this coordinator
  114. exclusions.removeElementAt(i);
  115. // update local info in each method involved
  116. for (int j = 0; j < methNames.length; j++) {
  117. Method aMeth = getOrSetMethod(methNames[j]);
  118. aMeth.removeExclusion(mux);
  119. }
  120. }
  121. }
  122. }
  123. }
  124. /**
  125. * This method is the guard for enforcing all synchronization and
  126. * coordination constraints of a given method, and it should be called
  127. * just before the method is executed.
  128. * In this form, only the method name is given. The only constraints
  129. * checked are the exclusion constraints.
  130. * If the method was previousely marked as selfex (through addSelfex),
  131. * guardedEntry ensures that the method is executed only when no other
  132. * thread is executing it.
  133. * If the method was previousely marked as being in one or more mutex
  134. * sets, guardedEntry ensures that the method is executed only when no other
  135. * thread is executing any of the methods with which the give method is
  136. * mutexed.
  137. */
  138. public synchronized void guardedEntry(String methName) {
  139. guardedEntry(methName, new Condition() {
  140. public boolean checkit() {
  141. return true;
  142. }
  143. }, null);
  144. }
  145. /**
  146. * Just like guardedEntry(String methName), but the given method is executed
  147. * only when the given condition is true.
  148. * guardedEntry is the guard for enforcing all synchronization and
  149. * coordination constraints of a given method, and it should be called
  150. * just before the method is executed.
  151. * In this form, the method name is given along with a condition.
  152. * The constraints checked are the exclusion constraints and whether
  153. * the given condition is true.
  154. * If the method was previousely marked as selfex (through addSelfex),
  155. * guardedEntry ensures that the method is executed only when no other
  156. * thread is executing it.
  157. * If the method was previousely marked as being in one or more mutex
  158. * sets, guardedEntry ensures that the method is executed only when no other
  159. * thread is executing any of the methods with which the give method is
  160. * mutexed.
  161. * If the condition is false, guardedEntry suspends the current thread.
  162. * That thread remains suspended until the condition becomes true, in
  163. * which case all constraints are rechecked before the method is executed.
  164. * When all exclusion constraints are checked and the given condition is
  165. * true, the given method is executed.
  166. */
  167. public synchronized void guardedEntry(String methName, Condition condition) {
  168. guardedEntry(methName, condition, null);
  169. }
  170. /**
  171. * Just like guardedEntry(String methName), but with an additional
  172. * coordination action that is executed before the given method is
  173. * executed.
  174. * guardedEntry is the guard for enforcing all synchronization and
  175. * coordination constraints of a given method, and it should be called
  176. * just before the method is executed.
  177. * In this form, the method name is given along with a coordination action.
  178. * The only constraints checked are the exclusion constraints.
  179. * If the method was previousely marked as selfex (through addSelfex),
  180. * guardedEntry ensures that the method is executed only when no other
  181. * thread is executing it.
  182. * If the method was previousely marked as being in one or more mutex
  183. * sets, guardedEntry ensures that the method is executed only when no other
  184. * thread is executing any of the methods with which the give method is
  185. * mutexed.
  186. * The given coordination action is executed just before the given method
  187. * is executed.
  188. */
  189. public synchronized void guardedEntry(String methName,
  190. CoordinationAction action) {
  191. guardedEntry(methName, new Condition() {
  192. public boolean checkit() {
  193. return true;
  194. }
  195. },
  196. action);
  197. }
  198. /**
  199. * Just like guardedEntry(String methName), but the given method is executed
  200. * only when the given condition is true; the additional
  201. * coordination action that is executed before the given method is
  202. * executed.
  203. * guardedEntry is the guard for enforcing all synchronization and
  204. * coordination constraints of a given method, and it should be called
  205. * just before the method is executed.
  206. * In this form, the method name is given along with a condition and
  207. * a coordination action.
  208. * The constraints checked are the exclusion constraints and whether the
  209. * given condition is true.
  210. * If the method was previousely marked as selfex (through addSelfex),
  211. * guardedEntry ensures that the method is executed only when no other
  212. * thread is executing it.
  213. * If the method was previousely marked as being in one or more mutex
  214. * sets, guardedEntry ensures that the method is executed only when no other
  215. * thread is executing any of the methods with which the give method is
  216. * mutexed.
  217. * If the condition is false, guardedEntry suspends the current thread.
  218. * That thread remains suspended until the condition becomes true, in
  219. * which case all constraints are rechecked before the method is executed.
  220. * When all exclusion constraints are checked and the given condition is
  221. * true, the given method is executed.
  222. * The given coordination action is executed just before the given method
  223. * is executed.
  224. */
  225. public synchronized void guardedEntry(String methName,
  226. Condition condition,
  227. CoordinationAction action) {
  228. Method aMeth = getOrSetMethod(methName);
  229. boolean canGo = false;
  230. // test pre-conditions for entering the method
  231. while (!canGo) {
  232. canGo = true;
  233. for (int i = 0; i < aMeth.exes.size() && canGo; i++)
  234. if (!((Exclusion)aMeth.exes.elementAt(i)).testExclusion(aMeth.name)) {
  235. canGo = false;
  236. }
  237. if (canGo && !condition.checkit()) {
  238. canGo = false;
  239. }
  240. if (!canGo)
  241. try {
  242. wait();
  243. } catch (InterruptedException e) { }
  244. }
  245. // OK.
  246. enterMethod(aMeth, action);
  247. }
  248. /**
  249. * This method is similar to guardedEntry, but it takes
  250. * an additional parameter - the milliseconds after which any suspension
  251. * will abort with a timeout.
  252. */
  253. public synchronized void guardedEntryWithTimeout(String methName,
  254. long millis)
  255. throws TimeoutException {
  256. guardedEntryWithTimeout(methName, new Condition() {
  257. public boolean checkit() {
  258. return true;
  259. }
  260. }, null, millis);
  261. }
  262. /**
  263. * This method is similar to guardedEntry, but it takes
  264. * an additional parameter - the milliseconds after which any suspension
  265. * will abort with a timeout.
  266. */
  267. public synchronized void guardedEntryWithTimeout(String methName,
  268. Condition condition,
  269. long millis)
  270. throws TimeoutException {
  271. guardedEntryWithTimeout(methName, condition, null, millis);
  272. }
  273. /**
  274. * This method is similar to guardedEntry, but it takes
  275. * an additional parameter - the milliseconds after which any suspension
  276. * will abort with a timeout.
  277. */
  278. public synchronized void guardedEntryWithTimeout(String methName,
  279. CoordinationAction action,
  280. long millis)
  281. throws TimeoutException {
  282. guardedEntryWithTimeout(methName, new Condition() {
  283. public boolean checkit() {
  284. return true;
  285. }
  286. }, action, millis);
  287. }
  288. /**
  289. * This method is similar to guardedEntry, but it takes
  290. * an additional parameter - the milliseconds after which any suspension
  291. * will abort with a timeout.
  292. */
  293. public synchronized void guardedEntryWithTimeout(String methName,
  294. Condition condition,
  295. CoordinationAction action,
  296. long millis)
  297. throws TimeoutException {
  298. Method aMeth = getOrSetMethod(methName);
  299. boolean canGo = false;
  300. long waitTime = millis;
  301. long startTime = System.currentTimeMillis();
  302. // test pre-conditions for entering the method
  303. while (!canGo) {
  304. canGo = true;
  305. for (int i = 0; i < aMeth.exes.size() && canGo; i++)
  306. if ((!((Exclusion)aMeth.exes.elementAt(i)).testExclusion(aMeth.name)) ||
  307. (!condition.checkit())) {
  308. canGo = false;
  309. }
  310. if (!canGo) {
  311. try {
  312. wait(waitTime);
  313. } catch (InterruptedException e) {}
  314. long now = System.currentTimeMillis();
  315. long timeSoFar = now - startTime;
  316. if (timeSoFar >= millis) // timeout!
  317. throw new TimeoutException(timeSoFar);
  318. else // adjust time
  319. waitTime = millis - timeSoFar;
  320. }
  321. }
  322. // OK.
  323. enterMethod(aMeth, action);
  324. }
  325. /**
  326. * This method provides the means for updating all synchronization and
  327. * coordination state after the execution of a given method, and it should be
  328. * called after the method is executed.
  329. * In this form, only the method name is given.
  330. * The synchronization state for self- and mutual-exclusion is
  331. * automatically upadted.
  332. */
  333. public synchronized void guardedExit(String methName) {
  334. guardedExit(methName, null);
  335. }
  336. /**
  337. * Just like guardedExit(String methName) but with an additional
  338. * coordination action that is executed.
  339. * guardedExit provides the means for updating all synchronization and
  340. * coordination state after the execution of a given method, and it should be
  341. * called after the method is executed.
  342. * In this form, the method name is given along with a coordination action.
  343. * The synchronization state for self- and mutual-exclusion is
  344. * automatically upadted.
  345. * The given coordination action is executed.
  346. */
  347. public synchronized void guardedExit(String methName,
  348. CoordinationAction action) {
  349. Method aMeth = getOrSetMethod(methName);
  350. for (int i = 0; i < aMeth.exes.size(); i++)
  351. ((Exclusion)aMeth.exes.elementAt(i)).exitExclusion(methName);
  352. if (action != null) action.doit();
  353. notifyAll();
  354. }
  355. private Method getOrSetMethod(String methName) {
  356. Method aMeth = null;
  357. if (!methods.containsKey(methName)) {
  358. methods.put(methName, (aMeth = new Method(methName)));
  359. }
  360. else {
  361. aMeth = (Method) methods.get(methName);
  362. }
  363. return aMeth;
  364. }
  365. private void enterMethod(Method aMeth, CoordinationAction action) {
  366. for (int i = 0; i < aMeth.exes.size(); i++)
  367. ((Exclusion)aMeth.exes.elementAt(i)).enterExclusion(aMeth.name);
  368. if (action != null) action.doit();
  369. }
  370. }
  371. class Method {
  372. String name;
  373. Vector exes = new Vector(3);
  374. Method(String n) {
  375. name = n;
  376. }
  377. void addExclusion(Exclusion ex) {
  378. exes.addElement(ex);
  379. }
  380. void removeExclusion(Exclusion ex) {
  381. for (int i = 0; i < exes.size(); i++) {
  382. if (exes.elementAt(i) == ex)
  383. exes.removeElementAt(i);
  384. }
  385. }
  386. }