1 19 20 package org.openide.util; 21 22 import java.awt.EventQueue ; 23 import java.lang.reflect.InvocationTargetException ; 24 import java.util.ArrayList ; 25 import java.util.HashMap ; 26 import java.util.LinkedList ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.logging.Level ; 30 import java.util.logging.Logger ; 31 32 82 public final class Mutex extends Object { 83 84 private static int counter; 85 86 87 private static Logger LOG = Logger.getLogger(Mutex.class.getName()); 88 89 116 public static final Mutex EVENT = new Mutex(); 117 118 121 static boolean beStrict; 122 123 125 126 private static final int NONE = 0x0; 127 128 129 private static final int CHAIN = 0x1; 130 131 132 private static final int X = 0x2; 133 134 135 private static final int S = 0x3; 136 137 138 private static final int MODE_COUNT = 0x4; 139 140 141 142 private static final boolean[][] cmatrix = {null, 144 null, { true, false, false, false },{ true, false, false, true } 146 }; 147 148 149 private int grantedMode = NONE; 150 151 152 private int origMode; 153 154 155 private Object LOCK; 156 157 158 private Map <Thread ,ThreadInfo> registeredThreads; 159 160 161 162 private int readersNo = 0; 164 165 166 private List <QueueCell> waiters; 167 168 169 private int cnt; 170 171 179 public Mutex(Object lock) { 180 init(lock); 181 } 182 183 185 public Mutex() { 186 init(new InternalLock()); 187 } 188 189 192 public Mutex(Privileged privileged) { 193 if (privileged == null) { 194 throw new IllegalArgumentException ("privileged == null"); } else { 196 init(new InternalLock()); 197 privileged.setParent(this); 198 } 199 } 200 201 202 private void init(Object lock) { 203 this.LOCK = lock; 204 this.registeredThreads = new HashMap <Thread ,ThreadInfo>(7); 205 this.waiters = new LinkedList <QueueCell>(); 206 this.cnt = counter++; 207 if (LOG.isLoggable(Level.FINE)) { 208 LOG.log(Level.FINE, "[" + cnt + "] created here", new Exception ()); 209 } 210 } 211 212 217 public <T> T readAccess(Action<T> action) { 218 if (this == EVENT) { 219 try { 220 return doEventAccess(action); 221 } catch (MutexException e) { 222 throw (InternalError ) new InternalError ("Exception from non-Exception Action").initCause(e.getException()); } 224 } 225 226 Thread t = Thread.currentThread(); 227 readEnter(t); 228 229 try { 230 return action.run(); 231 } finally { 232 leave(t); 233 } 234 } 235 236 260 public <T> T readAccess(ExceptionAction<T> action) throws MutexException { 261 if (this == EVENT) { 262 return doEventAccess(action); 263 } 264 265 Thread t = Thread.currentThread(); 266 readEnter(t); 267 268 try { 269 return action.run(); 270 } catch (RuntimeException e) { 271 throw e; 272 } catch (Exception e) { 273 throw new MutexException(e); 274 } finally { 275 leave(t); 276 } 277 } 278 279 285 public void readAccess(final Runnable action) { 286 if (this == EVENT) { 287 doEvent(action); 288 289 return; 290 } 291 292 Thread t = Thread.currentThread(); 293 readEnter(t); 294 295 try { 296 action.run(); 297 } finally { 298 leave(t); 299 } 300 } 301 302 308 public <T> T writeAccess(Action<T> action) { 309 if (this == EVENT) { 310 try { 311 return doEventAccess(action); 312 } catch (MutexException e) { 313 throw (InternalError ) new InternalError ("Exception from non-Exception Action").initCause(e.getException()); } 315 } 316 317 Thread t = Thread.currentThread(); 318 writeEnter(t); 319 320 try { 321 return action.run(); 322 } finally { 323 leave(t); 324 } 325 } 326 327 348 public <T> T writeAccess(ExceptionAction<T> action) throws MutexException { 349 if (this == EVENT) { 350 return doEventAccess(action); 351 } 352 353 Thread t = Thread.currentThread(); 354 writeEnter(t); 355 356 try { 357 return action.run(); 358 } catch (RuntimeException e) { 359 throw e; 360 } catch (Exception e) { 361 throw new MutexException(e); 362 } finally { 363 leave(t); 364 } 365 } 366 367 374 public void writeAccess(final Runnable action) { 375 if (this == EVENT) { 376 doEvent(action); 377 378 return; 379 } 380 381 Thread t = Thread.currentThread(); 382 writeEnter(t); 383 384 try { 385 action.run(); 386 } finally { 387 leave(t); 388 } 389 } 390 391 408 public boolean isReadAccess() { 409 if (this == EVENT) { 410 return javax.swing.SwingUtilities.isEventDispatchThread(); 411 } 412 413 Thread t = Thread.currentThread(); 414 ThreadInfo info; 415 416 synchronized (LOCK) { 417 info = getThreadInfo(t); 418 419 if (info != null) { 420 if (info.counts[S] > 0) { 421 return true; 422 } 423 } 424 } 425 426 return false; 427 } 428 429 437 public boolean isWriteAccess() { 438 if (this == EVENT) { 439 return javax.swing.SwingUtilities.isEventDispatchThread(); 440 } 441 442 Thread t = Thread.currentThread(); 443 ThreadInfo info; 444 445 synchronized (LOCK) { 446 info = getThreadInfo(t); 447 448 if (info != null) { 449 if (info.counts[X] > 0) { 450 return true; 451 } 452 } 453 } 454 455 return false; 456 } 457 458 472 public void postReadRequest(final Runnable run) { 473 postRequest(S, run); 474 } 475 476 489 public void postWriteRequest(Runnable run) { 490 postRequest(X, run); 491 } 492 493 494 public String toString() { 495 if (this == EVENT) { 496 return "Mutex.EVENT"; } 498 499 String newline = System.getProperty("line.separator"); 500 StringBuffer sbuff = new StringBuffer (512); 501 502 synchronized (LOCK) { 503 sbuff.append("threads: ").append(registeredThreads).append(newline); sbuff.append("readersNo: ").append(readersNo).append(newline); sbuff.append("waiters: ").append(waiters).append(newline); sbuff.append("grantedMode: ").append(grantedMode).append(newline); } 508 509 return sbuff.toString(); 510 } 511 512 514 515 private void writeEnter(Thread t) { 516 enter(X, t, true); 517 } 518 519 520 private void readEnter(Thread t) { 521 enter(S, t, true); 522 } 523 524 private void doLog(String action, Object ... params) { 525 String tid = Integer.toHexString(Thread.currentThread().hashCode()); 526 LOG.log(Level.FINE, "[#" + cnt + "@" + tid + "] " + action, params); 527 } 528 529 533 private boolean enter(int requested, Thread t, boolean block) { 534 boolean log = LOG.isLoggable(Level.FINE); 535 536 if (log) doLog("Entering {0}, {1}", requested, block); 538 boolean ret = enterImpl(requested, t, block); 539 540 if (log) doLog("Entering exit: {0}", ret); 542 return ret; 543 } 544 545 private boolean enterImpl(int requested, Thread t, boolean block) { 546 QueueCell cell = null; 547 int loopc = 0; 548 549 for (;;) { 550 loopc++; 551 synchronized (LOCK) { 552 ThreadInfo info = getThreadInfo(t); 554 555 if (info != null) { 556 if (grantedMode == NONE) { 557 throw new IllegalStateException (); 559 } 560 if (((info.mode == S) && (grantedMode == X)) || 564 ((info.mode == X) && (grantedMode == S))) { 565 throw new IllegalStateException (); 567 } 568 if ((info.mode == X) || (info.mode == requested)) { 569 if (info.forced) { 570 info.forced = false; 571 } else { 572 if ((requested == X) && (info.counts[S] > 0)) { 573 IllegalStateException e = new IllegalStateException ("WARNING: Going from readAccess to writeAccess, see #10778: http://www.netbeans.org/issues/show_bug.cgi?id=10778 "); 574 575 if (beStrict) { 576 throw e; 577 } 578 Exceptions.printStackTrace(e); 579 } 580 info.counts[requested]++; 581 if ((requested == S) && 582 (info.counts[requested] == 1)) { 583 readersNo++; 584 } 585 } 586 return true; 587 } else if (canUpgrade(info.mode, requested)) { 588 IllegalStateException e = new IllegalStateException ("WARNING: Going from readAccess to writeAccess, see #10778: http://www.netbeans.org/issues/show_bug.cgi?id=10778 "); 589 590 if (beStrict) { 591 throw e; 592 } 593 Exceptions.printStackTrace(e); 594 info.mode = X; 595 info.counts[requested]++; 596 info.rsnapshot = info.counts[S]; 597 if (grantedMode == S) { 598 setGrantedMode(X); 599 } else if (grantedMode == X) { 600 throw new IllegalStateException (); 602 } 603 return true; 605 } else { 606 IllegalStateException e = new IllegalStateException ("WARNING: Going from readAccess to writeAccess through queue, see #10778: http://www.netbeans.org/issues/show_bug.cgi?id=10778 "); 607 608 if (beStrict) { 609 throw e; 610 } 611 Exceptions.printStackTrace(e); 612 } 613 } else { 614 if (isCompatible(requested)) { 615 setGrantedMode(requested); 616 registeredThreads.put(t, 617 info = new ThreadInfo(t, requested)); 618 if (requested == S) { 619 readersNo++; 620 } 621 return true; 622 } 623 } 624 if (!block) { 625 return false; 626 } 627 setGrantedMode(CHAIN); 628 cell = chain(requested, t, 0); 629 } 630 cell.sleep(); 632 } 633 } 635 636 637 private boolean reenter(Thread t, int mode) { 638 boolean log = LOG.isLoggable(Level.FINE); 639 640 if (log) doLog("Re-Entering {0}", mode); 642 boolean ret = reenterImpl(t, mode); 643 644 if (log) doLog("Re-Entering exit: {0}", ret); 646 return ret; 647 } 648 649 650 private boolean reenterImpl(Thread t, int mode) { 651 if (mode == S) { 653 if ((grantedMode != NONE) && (grantedMode != S)) { 654 throw new IllegalStateException (this.toString()); 655 } 656 657 enter(mode, t, true); 658 659 return false; 660 } 661 662 ThreadInfo tinfo = getThreadInfo(t); 664 boolean chainFromLeaveX = ((grantedMode == CHAIN) && (tinfo != null) && (tinfo.counts[X] > 0)); 665 666 if ((grantedMode == X) || (grantedMode == NONE) || chainFromLeaveX) { 668 enter(mode, t, true); 669 670 return false; 671 } else { 673 if (readersNo == 0) { 674 throw new IllegalStateException (this.toString()); 675 } 676 677 ThreadInfo info = new ThreadInfo(t, mode); 678 registeredThreads.put(t, info); 679 680 readersNo += 2; 682 683 setGrantedMode(CHAIN); 685 686 return true; 687 } 688 } 690 691 692 private void privilegedEnter(Thread t, int mode) { 693 boolean decrease = true; 694 695 synchronized (LOCK) { 696 getThreadInfo(t); 697 } 698 699 for (;;) { 700 QueueCell cell; 701 702 synchronized (LOCK) { 703 if (decrease) { 704 decrease = false; 705 readersNo -= 2; 706 } 707 708 setGrantedMode(CHAIN); 712 cell = chain(mode, t, Integer.MAX_VALUE); 713 714 if (readersNo == 0) { 716 if (waiters.get(0) == cell) { 718 waiters.remove(0); 719 720 setGrantedMode(mode); 721 722 return; 723 } else { 724 setGrantedMode(NONE); 725 wakeUpOthers(); 726 } 727 } 728 } 729 731 cell.sleep(); 732 733 } 735 } 736 737 738 private void leave(Thread t) { 739 boolean log = LOG.isLoggable(Level.FINE); 740 741 if (log) doLog("Leaving {0}", grantedMode); 743 leaveImpl(t); 744 745 if (log) doLog("Leaving exit: {0}", grantedMode); } 747 748 private void leaveImpl(Thread t) { 749 ThreadInfo info; 750 int postedMode = NONE; 751 boolean needLock = false; 752 753 synchronized (LOCK) { 754 info = getThreadInfo(t); 755 756 switch (grantedMode) { 757 case NONE: 758 throw new IllegalStateException (); 759 760 case CHAIN: 761 762 if (info.counts[X] > 0) { 763 postedMode = leaveX(info); 765 } else if (info.counts[S] > 0) { 766 postedMode = leaveS(info); 767 } else { 768 throw new IllegalStateException (); 769 } 770 771 break; 772 773 case X: 774 postedMode = leaveX(info); 775 776 break; 777 778 case S: 779 postedMode = leaveS(info); 780 781 break; 782 } 784 if (postedMode != NONE) { 786 int runsize = info.getRunnableCount(postedMode); 787 788 if (runsize != 0) { 789 needLock = reenter(t, postedMode); } 791 } 792 } 794 if ((postedMode != NONE) && (info.getRunnableCount(postedMode) > 0)) { 796 doLog("Processing posted requests: {0}", postedMode); try { 798 if (needLock) { privilegedEnter(t, postedMode); 800 } 801 802 List runnables = info.dequeue(postedMode); 804 final int size = runnables.size(); 805 806 for (int i = 0; i < size; i++) { 807 try { 808 Runnable r = (Runnable ) runnables.get(i); 809 810 r.run(); 811 } 812 catch (Exception e) { 813 Exceptions.printStackTrace(e); 814 } 815 catch (StackOverflowError e) { 816 e.printStackTrace(); 818 Exceptions.printStackTrace(e); 819 } 820 catch (ThreadDeath td) { 821 throw td; 822 } 823 catch (Error e) { 824 Exceptions.printStackTrace(e); 825 } 826 } 827 829 runnables = null; 831 } finally { 832 leave(t); } 834 } 835 } 837 838 839 private int leaveX(ThreadInfo info) { 840 if ((info.counts[X] <= 0) || (info.rsnapshot > info.counts[S])) { 841 throw new IllegalStateException (); 843 } 844 845 if (info.rsnapshot == info.counts[S]) { 846 info.counts[X]--; 847 848 if (info.counts[X] == 0) { 849 info.rsnapshot = 0; 850 851 if (info.counts[S] > 0) { 853 info.mode = S; 854 setGrantedMode(S); 855 } else { 856 info.mode = NONE; 857 setGrantedMode(NONE); 858 registeredThreads.remove(info.t); 859 } 860 861 if (info.getRunnableCount(S) > 0) { 862 wakeUpReaders(); 864 865 return S; 866 } 867 868 wakeUpOthers(); 870 } 871 } else { 872 if (info.counts[S] <= 0) { 874 throw new IllegalStateException (); 876 } 877 878 if (--info.counts[S] == 0) { 879 if (readersNo <= 0) { 880 throw new IllegalStateException (); 881 } 882 883 readersNo--; 884 885 return X; 886 } 887 } 888 889 return NONE; 890 } 891 892 893 private int leaveS(ThreadInfo info) { 894 if ((info.counts[S] <= 0) || (info.counts[X] > 0)) { 895 throw new IllegalStateException (); 897 } 898 899 info.counts[S]--; 900 901 if (info.counts[S] == 0) { 902 info.mode = NONE; 904 registeredThreads.remove(info.t); 905 906 if (readersNo <= 0) { 908 throw new IllegalStateException (); 909 } 910 911 readersNo--; 912 913 if (readersNo == 0) { 914 setGrantedMode(NONE); 918 919 if (info.getRunnableCount(X) > 0) { 920 return X; 921 } 922 923 wakeUpOthers(); 924 } else if (info.getRunnableCount(X) > 0) { 925 return X; 926 } else if ((grantedMode == CHAIN) && (readersNo == 1)) { 927 for (int i = 0; i < waiters.size(); i++) { 929 QueueCell qc = waiters.get(i); 930 931 synchronized (qc) { 932 if (qc.isGotOut()) { 933 waiters.remove(i--); 934 935 continue; 936 } 937 938 ThreadInfo tinfo = getThreadInfo(qc.t); 939 940 if (tinfo != null) { 941 if (tinfo.mode == S) { 942 if (qc.mode != X) { 943 throw new IllegalStateException (); 945 } 946 947 if (waiters.size() == 1) { 948 setGrantedMode(X); 949 } 950 952 tinfo.mode = X; 953 waiters.remove(i); 954 qc.wakeMeUp(); 955 } 956 } 957 959 break; 960 } 961 } 963 } 965 } 967 969 return NONE; 970 } 971 972 975 private QueueCell chain(final int requested, final Thread t, final int priority) { 976 978 984 QueueCell qc = new QueueCell(requested, t); 985 986 qc.priority2 = priority; 988 989 final int size = waiters.size(); 990 991 if (size == 0) { 992 waiters.add(qc); 993 } else if (qc.getPriority() == Integer.MAX_VALUE) { 994 waiters.add(0, qc); 995 } else { 996 QueueCell cursor; 997 int i = 0; 998 999 do { 1000 cursor = waiters.get(i); 1001 1002 if (cursor.getPriority() < qc.getPriority()) { 1003 waiters.add(i, qc); 1004 1005 break; 1006 } 1007 1008 i++; 1009 } while (i < size); 1010 1011 if (i == size) { 1012 waiters.add(qc); 1013 } 1014 } 1015 1016 return qc; 1017 } 1018 1019 1020 private void wakeUpOthers() { 1021 if ((grantedMode == X) || (grantedMode == CHAIN)) { 1022 throw new IllegalStateException (); 1024 } 1025 1026 if (waiters.size() == 0) { 1027 return; 1028 } 1029 1030 for (int i = 0; i < waiters.size(); i++) { 1031 QueueCell qc = waiters.get(i); 1032 1033 synchronized (qc) { 1034 if (qc.isGotOut()) { 1035 waiters.remove(i--); 1037 1038 continue; 1039 } 1040 1041 if (isCompatible(qc.mode)) { waiters.remove(i--); 1043 qc.wakeMeUp(); 1044 setGrantedMode(qc.mode); 1045 1046 if (getThreadInfo(qc.t) == null) { 1047 ThreadInfo ti = new ThreadInfo(qc.t, qc.mode); 1050 ti.forced = true; 1051 1052 if (qc.mode == S) { 1053 readersNo++; 1054 } 1055 1056 registeredThreads.put(qc.t, ti); 1057 } 1058 } else { 1059 setGrantedMode(CHAIN); 1060 1061 break; 1062 } 1063 } 1064 } 1066 } 1067 1068 private void wakeUpReaders() { 1069 assert (grantedMode == NONE) || (grantedMode == S); 1070 1071 if (waiters.size() == 0) { 1072 return; 1073 } 1074 1075 for (int i = 0; i < waiters.size(); i++) { 1076 QueueCell qc = waiters.get(i); 1077 1078 synchronized (qc) { 1079 if (qc.isGotOut()) { 1080 waiters.remove(i--); 1082 1083 continue; 1084 } 1085 1086 if (qc.mode == S) { waiters.remove(i--); 1088 qc.wakeMeUp(); 1089 setGrantedMode(S); 1090 1091 if (getThreadInfo(qc.t) == null) { 1092 ThreadInfo ti = new ThreadInfo(qc.t, qc.mode); 1095 ti.forced = true; 1096 readersNo++; 1097 registeredThreads.put(qc.t, ti); 1098 } 1099 } 1100 } 1101 } 1103 } 1104 1105 1109 private void postRequest(int mutexMode, Runnable run) { 1110 if (this == EVENT) { 1111 doEventRequest(run); 1112 1113 return; 1114 } 1115 1116 Thread t = Thread.currentThread(); 1117 ThreadInfo info; 1118 1119 synchronized (LOCK) { 1120 info = getThreadInfo(t); 1121 1122 if (info != null) { 1123 if ((mutexMode == info.mode) && (info.counts[(S + X) - mutexMode] == 0)) { 1126 enter(mutexMode, t, true); 1127 } else { info.enqueue(mutexMode, run); 1129 1130 return; 1131 } 1132 } 1133 } 1134 1135 if (info == null) { 1137 enter(mutexMode, t, true); 1138 1139 try { 1140 run.run(); 1141 } finally { 1142 leave(t); 1143 } 1144 1145 return; 1146 } 1147 1148 try { 1151 run.run(); 1152 } finally { 1153 leave(t); 1154 } 1155 } 1156 1157 1160 private boolean isCompatible(int requested) { 1161 if (requested == S && grantedMode == CHAIN && origMode == S) return true; 1163 return cmatrix[requested][grantedMode]; 1164 } 1165 1166 private ThreadInfo getThreadInfo(Thread t) { 1167 return registeredThreads.get(t); 1168 } 1169 1170 private boolean canUpgrade(int threadGranted, int requested) { 1171 return (threadGranted == S) && (requested == X) && (readersNo == 1); 1172 } 1173 1174 1176 1179 private static void doEvent(Runnable run) { 1180 if (EventQueue.isDispatchThread()) { 1181 run.run(); 1182 } else { 1183 EventQueue.invokeLater(run); 1184 } 1185 } 1186 1187 1190 private static void doEventRequest(Runnable run) { 1191 EventQueue.invokeLater(run); 1192 } 1193 1194 1197 private static <T> T doEventAccess(final ExceptionAction<T> run) 1198 throws MutexException { 1199 if (isDispatchThread()) { 1200 try { 1201 return run.run(); 1202 } catch (RuntimeException e) { 1203 throw e; 1204 } catch (Exception e) { 1205 throw new MutexException(e); 1206 } 1207 } 1208 1209 final Throwable [] arr = new Throwable [1]; 1210 1211 try { 1212 final List <T> res = new ArrayList <T>(1); 1213 class AWTWorker implements Runnable { 1214 public void run() { 1215 try { 1216 res.add(run.run()); 1217 } catch (Exception e) { 1218 arr[0] = e; 1219 } catch (LinkageError e) { 1220 arr[0] = e; 1222 } catch (StackOverflowError e) { 1223 arr[0] = e; 1225 } 1226 } 1227 } 1228 1229 AWTWorker w = new AWTWorker(); 1230 EventQueue.invokeAndWait(w); 1231 1232 if (arr[0] == null) { 1233 return res.get(0); 1234 } 1235 } catch (InterruptedException e) { 1236 arr[0] = e; 1237 } catch (InvocationTargetException e) { 1238 arr[0] = e; 1239 } 1240 1241 if (arr[0] instanceof RuntimeException ) { 1242 throw (RuntimeException ) arr[0]; 1243 } 1244 1245 throw notifyException(arr[0]); 1246 } 1247 1248 1249 static boolean isDispatchThread() { 1250 boolean dispatch = EventQueue.isDispatchThread(); 1251 1252 if (!dispatch && (Utilities.getOperatingSystem() == Utilities.OS_SOLARIS)) { 1253 dispatch = (Thread.currentThread().getClass().getName().indexOf("EventDispatchThread") >= 0); } 1257 1258 return dispatch; 1259 } 1260 1261 1262 private static final MutexException notifyException(Throwable t) { 1263 if (t instanceof InvocationTargetException ) { 1264 t = unfoldInvocationTargetException((InvocationTargetException ) t); 1265 } 1266 1267 if (t instanceof Error ) { 1268 annotateEventStack(t); 1269 throw (Error ) t; 1270 } 1271 1272 if (t instanceof RuntimeException ) { 1273 annotateEventStack(t); 1274 throw (RuntimeException ) t; 1275 } 1276 1277 MutexException exc = new MutexException((Exception ) t); 1278 exc.initCause(t); 1279 1280 return exc; 1281 } 1282 1283 private static final void annotateEventStack(Throwable t) { 1284 } 1286 1287 private static final Throwable unfoldInvocationTargetException(InvocationTargetException e) { 1288 Throwable ret; 1289 1290 do { 1291 ret = e.getTargetException(); 1292 1293 if (ret instanceof InvocationTargetException ) { 1294 e = (InvocationTargetException ) ret; 1295 } else { 1296 e = null; 1297 } 1298 } while (e != null); 1299 1300 return ret; 1301 } 1302 1303 1305 1309 public interface Action<T> extends ExceptionAction<T> { 1310 1313 T run(); 1314 } 1315 1316 1323 public interface ExceptionAction<T> { 1324 1329 T run() throws Exception ; 1330 } 1331 1332 private static final class ThreadInfo { 1333 1334 boolean forced; 1335 1336 1337 final Thread t; 1338 1339 1340 int mode; 1341 1342 1344 1345 int[] counts; 1346 1347 1350 List <Runnable >[] queues; 1351 1352 1364 int rsnapshot; 1365 1366 @SuppressWarnings ("unchecked") 1367 public ThreadInfo(Thread t, int mode) { 1368 this.t = t; 1369 this.mode = mode; 1370 this.counts = new int[MODE_COUNT]; 1371 this.queues = (List <Runnable >[])new List [MODE_COUNT]; 1372 counts[mode] = 1; 1373 } 1374 1375 public String toString() { 1376 return super.toString() + " thread: " + t + " mode: " + mode + " X: " + counts[2] + " S: " + counts[3]; } 1378 1379 1380 public void enqueue(int mode, Runnable run) { 1381 if (queues[mode] == null) { 1382 queues[mode] = new ArrayList <Runnable >(13); 1383 } 1384 1385 queues[mode].add(run); 1386 } 1387 1388 1389 public List dequeue(int mode) { 1390 List ret = queues[mode]; 1391 queues[mode] = null; 1392 1393 return ret; 1394 } 1395 1396 public int getRunnableCount(int mode) { 1397 return ((queues[mode] == null) ? 0 : queues[mode].size()); 1398 } 1399 } 1400 1401 1405 private static final class InternalLock { 1406 InternalLock() { 1407 } 1408 } 1409 1410 private static final class QueueCell { 1411 int mode; 1412 Thread t; 1413 boolean signal; 1414 boolean left; 1415 1416 1417 int priority2; 1418 1419 public QueueCell(int mode, Thread t) { 1420 this.mode = mode; 1421 this.t = t; 1422 this.left = false; 1423 this.priority2 = 0; 1424 } 1425 1426 public String toString() { 1427 return super.toString() + " mode: " + mode + " thread: " + t; } 1429 1430 1431 public long getPriority() { 1432 return ((priority2 == 0) ? t.getPriority() : priority2); 1433 } 1434 1435 1436 public boolean isGotOut() { 1437 return left; 1438 } 1439 1440 1443 public synchronized void sleep() { 1444 try { 1445 while (!signal) { 1446 try { 1447 wait(); 1448 1449 return; 1450 } catch (InterruptedException e) { 1451 Logger.getLogger(Mutex.class.getName()).log(Level.WARNING, null, e); 1452 } 1453 } 1454 } finally { 1455 left = true; 1456 } 1457 } 1458 1459 1460 public void wakeMeUp() { 1461 signal = true; 1462 notifyAll(); 1463 } 1464 } 1465 1466 1485 public static final class Privileged { 1486 private Mutex parent; 1487 1488 final void setParent(Mutex parent) { 1489 this.parent = parent; 1490 } 1491 1492 public void enterReadAccess() { 1493 parent.readEnter(Thread.currentThread()); 1494 } 1495 1496 public void enterWriteAccess() { 1497 parent.writeEnter(Thread.currentThread()); 1498 } 1499 1500 public void exitReadAccess() { 1501 parent.leave(Thread.currentThread()); 1502 } 1503 1504 public void exitWriteAccess() { 1505 parent.leave(Thread.currentThread()); 1506 } 1507 } 1508 1509 private void setGrantedMode(int mode) { 1510 if (grantedMode != CHAIN && mode == CHAIN) { 1511 origMode = grantedMode; 1512 } 1513 grantedMode = mode; 1514 } 1515} 1516 | Popular Tags |