1 /*
2  * Created on 9 Aug 2006
3  * Created by Paul Gardner
4  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  */
19 
20 package org.gudy.azureus2.core3.util;
21 
22 public class
23 FrequencyLimitedDispatcher
24 {
25 	private AERunnable	target;
26 	private long		min_millis;
27 
28 	private long			last_run;
29 	private DelayedEvent	delay_event;
30 
31 	public
FrequencyLimitedDispatcher( AERunnable _target, int _min_frequency_millis )32 	FrequencyLimitedDispatcher(
33 		AERunnable			_target,
34 		int					_min_frequency_millis )
35 	{
36 		target		= _target;
37 		min_millis	= _min_frequency_millis;
38 	}
39 
40 	public void
setSingleThreaded()41 	setSingleThreaded()
42 	{
43 		final AERunnable old_target = target;
44 
45 		target =
46 			new AERunnable()
47 			{
48 				private boolean	running;
49 				private boolean	pending;
50 
51 				public void
52 				runSupport()
53 				{
54 					synchronized( this ){
55 
56 						if ( running ){
57 
58 							pending = true;
59 
60 							return;
61 						}
62 
63 						running = true;
64 					}
65 
66 					try{
67 						old_target.runSupport();
68 
69 					}finally{
70 
71 						boolean	was_pending;
72 
73 						synchronized( this ){
74 
75 							running = false;
76 
77 							was_pending = pending;
78 
79 							pending = false;
80 						}
81 
82 						if ( was_pending ){
83 
84 							dispatch();
85 						}
86 					}
87 				}
88 			};
89 	}
90 
91 	public void
dispatch()92 	dispatch()
93 	{
94 		long	now = SystemTime.getMonotonousTime();
95 
96 		boolean	run_it	= false;
97 
98 		synchronized( this ){
99 
100 			if ( delay_event == null ){
101 
102 				long	delay = min_millis - (now - last_run );
103 
104 				if ( now < last_run || delay <= 0 ){
105 
106 					last_run	= now;
107 
108 					run_it		= true;
109 
110 				}else{
111 
112 						// run too recently
113 
114 					delay_event =
115 						new DelayedEvent(
116 							"FreqLimDisp",
117 							delay,
118 							new AERunnable()
119 							{
120 								public void
121 								runSupport()
122 								{
123 									long	now = SystemTime.getMonotonousTime();
124 
125 									synchronized( FrequencyLimitedDispatcher.this ){
126 
127 										last_run = now;
128 
129 										delay_event	= null;
130 									}
131 
132 									target.run();
133 								}
134 							});
135 				}
136 			}
137 		}
138 
139 		if ( run_it ){
140 
141 			target.run();
142 		}
143 	}
144 }
145