package com.firefly.utils.time;

import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;

public class HashTimeWheel {
	private int maxTimers = 60; // wheel的格子数量
	private long interval = 1000; // wheel旋转时间间隔
	
	private ConcurrentLinkedQueue<TimerTask>[] timerSlots;
	private volatile int currentSlot = 0;
	private volatile boolean start;

	public int getMaxTimers() {
		return maxTimers;
	}

	public void setMaxTimers(int maxTimers) {
		this.maxTimers = maxTimers;
	}

	public long getInterval() {
		return interval;
	}

	public void setInterval(long interval) {
		this.interval = interval;
	}

	/**
	 * add a task
	 * 
	 * @param delay
	 *           after x milliseconds than execute runnable
	 * @param run
	 *           run task in future
	 */
	public Future add(long delay, Runnable run) {
		final int curSlot = currentSlot;
		
		final int ticks = delay > interval ? (int) (delay / interval) : 1; // 计算刻度长度
		final int index = (curSlot + (ticks % maxTimers)) % maxTimers; // 放到wheel的位置
		final int round = (ticks - 1) / maxTimers; // wheel旋转的圈数

		TimerTask task = new TimerTask(round, run);
		timerSlots[index].add(task);
		
		return new Future(this, index, task);
	}
	
	private final boolean remove(TimerTask task, int index) {
		return timerSlots[index].remove(task);
	}

	@SuppressWarnings("unchecked")
	public void start() {
		if (!start) {
			synchronized (this) {
				if (!start) {
					timerSlots = new ConcurrentLinkedQueue[maxTimers];
					for (int i = 0; i < timerSlots.length; i++) {
						timerSlots[i] = new ConcurrentLinkedQueue<TimerTask>();
					}

					start = true;
					new Thread(new Worker(), "firefly time wheel").start();
				}
			}
		}
	}

	public void stop() {
		start = false;
		timerSlots = null;
	}

	private final class Worker implements Runnable {

		@Override
		public void run() {
			while (start) {
				int currentSlotTemp = currentSlot;
				ConcurrentLinkedQueue<TimerTask> timerSlot = timerSlots[currentSlotTemp++];
				currentSlotTemp %= timerSlots.length;

				for (Iterator<TimerTask> iterator = timerSlot.iterator(); iterator
						.hasNext();) {
					if (iterator.next().runTask())
						iterator.remove();
				}

				try {
					Thread.sleep(interval);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				currentSlot = currentSlotTemp;
			}

		}

	}

	private final class TimerTask {
		private int round;
		private Runnable run;

		public TimerTask(int round, Runnable run) {
			this.round = round;
			this.run = run;
		}

		public boolean runTask() {
			if (round == 0) {
				run.run();
				return true;
			} else {
				round--;
				return false;
			}
		}
	}
	
	public static class Future {
		private HashTimeWheel timeWheel;
		private int index;
		private TimerTask task;
		
		public Future(HashTimeWheel timeWheel, int index, TimerTask task) {
			super();
			this.timeWheel = timeWheel;
			this.index = index;
			this.task = task;
		}



		public boolean cancel() {
			return timeWheel.remove(task, index);
		}
	}

}

@@ -170,18 +170,30 @@
  // 
+slot's number in 
 wheel
-%E7%9A%84%E6%A0%BC%E5%AD%90%E6%95%B0%E9%87%8F
 %0A%09pr
@@ -227,19 +227,28 @@
  // 
-wheel%E6%97%8B%E8%BD%AC%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94
+the clock's accuracy
 %0A%09%0A%09
@@ -944,14 +944,38 @@
  // 
-%E8%AE%A1%E7%AE%97%E5%88%BB%E5%BA%A6%E9%95%BF%E5%BA%A6
+figure out how many ticks need
 %0A%09%09f
@@ -1043,18 +1043,36 @@
  // 
-%E6%94%BE%E5%88%B0wheel%E7%9A%84%E4%BD%8D%E7%BD%AE
+figure out the wheel's index
 %0A%09%09f
@@ -1120,18 +1120,32 @@
  // 
-wheel%E6%97%8B%E8%BD%AC%E7%9A%84%E5%9C%88%E6%95%B0
+the round number of spin
 %0A%0A%09%09
@@ -3000,17 +3000,124 @@
 k;%0A%09%09%7D%0A%0A
-%0A
+%09%09/**%0A%09%09 * cancel current task%0A%09%09 * @return if it return true, which cancel task success, else it fail%0A%09%09 */
 %0A%09%09publi

add comment