1- use alloc:: { boxed :: Box , vec} ;
1+ use alloc:: vec;
22
3- use java_class_proto:: JavaMethodProto ;
3+ use java_class_proto:: { JavaFieldProto , JavaMethodProto } ;
44use jvm:: { ClassInstanceRef , Jvm , Result } ;
55
6- use crate :: { RuntimeClassProto , RuntimeContext , SpawnCallback , classes:: java:: util:: TimerTask } ;
6+ use crate :: {
7+ RuntimeClassProto , RuntimeContext ,
8+ classes:: java:: util:: { TimerTask , Vector } ,
9+ } ;
710
811// class java.util.Timer
912pub struct Timer ;
@@ -17,16 +20,35 @@ impl Timer {
1720 methods : vec ! [
1821 JavaMethodProto :: new( "<init>" , "()V" , Self :: init, Default :: default ( ) ) ,
1922 JavaMethodProto :: new( "schedule" , "(Ljava/util/TimerTask;JJ)V" , Self :: schedule, Default :: default ( ) ) ,
23+ JavaMethodProto :: new(
24+ "scheduleAtFixedRate" ,
25+ "(Ljava/util/TimerTask;JJ)V" ,
26+ Self :: schedule_at_fixed_rate,
27+ Default :: default ( ) ,
28+ ) ,
29+ ] ,
30+ fields : vec ! [
31+ JavaFieldProto :: new( "tasks" , "Ljava/util/Vector;" , Default :: default ( ) ) ,
32+ JavaFieldProto :: new( "thread" , "Ljava/lang/Thread;" , Default :: default ( ) ) ,
2033 ] ,
21- fields : vec ! [ ] ,
2234 }
2335 }
2436
25- async fn init ( jvm : & Jvm , _: & mut RuntimeContext , this : ClassInstanceRef < Self > ) -> Result < ( ) > {
37+ async fn init ( jvm : & Jvm , _: & mut RuntimeContext , mut this : ClassInstanceRef < Self > ) -> Result < ( ) > {
2638 tracing:: debug!( "java.util.Timer::<init>({:?})" , & this) ;
2739
2840 let _: ( ) = jvm. invoke_special ( & this, "java/lang/Object" , "<init>" , "()V" , ( ) ) . await ?;
2941
42+ let tasks = jvm. new_class ( "java/util/Vector" , "()V" , ( ) ) . await ?;
43+ let timer_thread = jvm
44+ . new_class ( "java/util/Timer$TimerThread" , "(Ljava/util/Vector;)V" , ( tasks. clone ( ) , ) )
45+ . await ?;
46+
47+ jvm. put_field ( & mut this, "tasks" , "Ljava/util/Vector;" , tasks) . await ?;
48+ jvm. put_field ( & mut this, "thread" , "Ljava/lang/Thread;" , timer_thread. clone ( ) ) . await ?;
49+
50+ let _: ( ) = jvm. invoke_virtual ( & timer_thread, "start" , "()V" , ( ) ) . await ?;
51+
3052 Ok ( ( ) )
3153 }
3254
@@ -40,40 +62,47 @@ impl Timer {
4062 ) -> Result < ( ) > {
4163 tracing:: debug!( "java.util.Timer::schedule({:?}, {:?}, {:?}, {:?})" , & this, & task, delay, period) ;
4264
43- // TODO we should not spawn new thread every time
65+ let now: i64 = context. now ( ) as i64 ;
66+ let next_execution_time = now + delay;
4467
45- struct TimerProxy {
46- jvm : Jvm ,
47- task : ClassInstanceRef < TimerTask > ,
48- delay : i64 ,
49- period : i64 ,
50- }
68+ Self :: do_schedule ( jvm, this, task, next_execution_time, period) . await
69+ }
5170
52- #[ async_trait:: async_trait]
53- impl SpawnCallback for TimerProxy {
54- #[ tracing:: instrument( name = "timer" , skip_all) ]
55- async fn call ( & self ) -> Result < ( ) > {
56- self . jvm . attach_thread ( ) ?;
71+ async fn schedule_at_fixed_rate (
72+ jvm : & Jvm ,
73+ context : & mut RuntimeContext ,
74+ this : ClassInstanceRef < Self > ,
75+ task : ClassInstanceRef < TimerTask > ,
76+ delay : i64 ,
77+ period : i64 ,
78+ ) -> Result < ( ) > {
79+ tracing:: debug!(
80+ "java.util.Timer::scheduleAtFixedRate({:?}, {:?}, {:?}, {:?})" ,
81+ & this,
82+ & task,
83+ delay,
84+ period
85+ ) ;
86+ // FIXME: fixed rate is not different from normal rate
5787
58- let _: ( ) = self . jvm . invoke_static ( "java/lang/Thread" , "sleep" , "(J)V" , ( self . delay , ) ) . await ?;
88+ let now: i64 = context. now ( ) as i64 ;
89+ let next_execution_time = now + delay;
5990
60- loop {
61- let _ : ( ) = self . jvm . invoke_virtual ( & self . task , "run" , "()V" , ( ) ) . await ? ;
91+ Self :: do_schedule ( jvm , this , task , next_execution_time , period ) . await
92+ }
6293
63- let _: ( ) = self . jvm . invoke_static ( "java/lang/Thread" , "sleep" , "(J)V" , ( self . period , ) ) . await ?;
64- }
65- }
66- }
94+ async fn do_schedule (
95+ jvm : & Jvm ,
96+ this : ClassInstanceRef < Self > ,
97+ mut task : ClassInstanceRef < TimerTask > ,
98+ next_execution_time : i64 ,
99+ period : i64 ,
100+ ) -> Result < ( ) > {
101+ jvm. put_field ( & mut task, "nextExecutionTime" , "J" , next_execution_time) . await ?;
102+ jvm. put_field ( & mut task, "period" , "J" , period) . await ?;
67103
68- context. spawn (
69- jvm,
70- Box :: new ( TimerProxy {
71- jvm : jvm. clone ( ) ,
72- task,
73- delay,
74- period,
75- } ) ,
76- ) ;
104+ let tasks: ClassInstanceRef < Vector > = jvm. get_field ( & this, "tasks" , "Ljava/util/Vector;" ) . await ?;
105+ let _: bool = jvm. invoke_virtual ( & tasks, "add" , "(Ljava/lang/Object;)Z" , ( task, ) ) . await ?;
77106
78107 Ok ( ( ) )
79108 }
0 commit comments