00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package com.realtime.crossfire.jxclient.timeouts;
00023
00024 import java.util.IdentityHashMap;
00025 import java.util.Map;
00026 import java.util.PriorityQueue;
00027 import org.jetbrains.annotations.NotNull;
00028
00035 public class Timeouts {
00036
00041 @NotNull
00042 private static final PriorityQueue<Event> EVENTS = new PriorityQueue<Event>();
00043
00048 @NotNull
00049 private static final Map<TimeoutEvent, Event> TIMEOUT_EVENTS = new IdentityHashMap<TimeoutEvent, Event>();
00050
00054 @NotNull
00055 private static final Runnable DELIVER_PENDING_TIMEOUTS = new Runnable() {
00056
00057 @Override
00058 public void run() {
00059 try {
00060 boolean doWait = true;
00061 while (!Thread.currentThread().isInterrupted()) {
00062 final Event event;
00063 final boolean execute;
00064 synchronized (EVENTS) {
00065 if (doWait) {
00066 doWait = false;
00067 final Event tmp = EVENTS.peek();
00068 if (tmp == null) {
00069 EVENTS.wait();
00070 } else {
00071
00072 EVENTS.wait(tmp.getTimeout()-System.currentTimeMillis());
00073 }
00074 }
00075
00076 event = EVENTS.peek();
00077
00078 execute = event != null && event.getTimeout() <= System.currentTimeMillis();
00079 if (execute) {
00080 EVENTS.poll();
00081 }
00082 }
00083 if (execute) {
00084 event.getTimeoutEvent().timeout();
00085 } else {
00086 doWait = true;
00087 }
00088 }
00089 } catch (final InterruptedException ignored) {
00090 Thread.currentThread().interrupt();
00091 }
00092 }
00093
00094 };
00095
00096 static {
00097 new Thread(DELIVER_PENDING_TIMEOUTS, "JXClient:Timeouts").start();
00098 }
00099
00103 private Timeouts() {
00104 }
00105
00112 public static void reset(final int timeout, @NotNull final TimeoutEvent timeoutEvent) {
00113 synchronized (EVENTS) {
00114 remove(timeoutEvent);
00115 add(timeout, timeoutEvent);
00116 }
00117 }
00118
00124 private static void add(final int timeout, @NotNull final TimeoutEvent timeoutEvent) {
00125 synchronized (EVENTS) {
00126 assert !TIMEOUT_EVENTS.containsKey(timeoutEvent);
00127
00128 final Event event = new Event(timeout, timeoutEvent);
00129 TIMEOUT_EVENTS.put(timeoutEvent, event);
00130 EVENTS.add(event);
00131 EVENTS.notifyAll();
00132 }
00133 }
00134
00140 public static void remove(@NotNull final TimeoutEvent timeoutEvent) {
00141 synchronized (EVENTS) {
00142 final Event event = TIMEOUT_EVENTS.remove(timeoutEvent);
00143 if (event != null) {
00144 EVENTS.remove(event);
00145 }
00146 }
00147 }
00148
00149 }