summaryrefslogtreecommitdiffstats
blob: 2baae3d7fdcfadfeb9326570f4af51f6fe42e7bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * Copyright (c) 2010 Remko Tronçon
 * Licensed under the GNU General Public License v3.
 * See Documentation/Licenses/GPLv3.txt for more information.
 */
/*
 * Copyright (c) 2010-2018, Isode Limited, London, England.
 * All rights reserved.
 */
package com.isode.stroke.network;

import com.isode.stroke.eventloop.Event;
import com.isode.stroke.eventloop.EventLoop;
import com.isode.stroke.eventloop.EventOwner;

class JavaTimer extends Timer {

    private class TimerRunnable implements Runnable,EventOwner {

        private boolean running_ = true;
        private final EventLoop eventLoop_;
        private final long milliseconds_;

        public TimerRunnable(EventLoop eventLoop, long milliseconds) {
            eventLoop_ = eventLoop;
            milliseconds_ = milliseconds;
        }

        public void run() {
            long endTime = System.currentTimeMillis() + milliseconds_;
            while (shouldEmit() && System.currentTimeMillis() < endTime) {
                try {
                    long timeToWait = endTime - System.currentTimeMillis();
                    if (timeToWait > 0) {
                        Thread.sleep(timeToWait);
                    }
                } catch (InterruptedException ex) {
                    // Needs to be caught, but won't break out of the loop
                    // unless end time reached or stop() has been called.
                }
            }
            synchronized(this) {
                if (shouldEmit()) {
                    eventLoop_.postEvent(new Event.Callback() {
                        public void run() {
                            onTick.emit();
                        }
                    },this);
                }  
            }     
        }


        synchronized boolean shouldEmit() {
            return running_;
        }

        public synchronized void stop() {
            running_ = false;
            timer_.eventLoop_.removeEventsFromOwner(this);
        }
    }

    /**
     * Create a new JavaTimer
     * @param eventLoop the caller's EventLoop. Should not be null.
     * @param milliseconds length of delay.
     */
    public JavaTimer(EventLoop eventLoop, long milliseconds) {
        timer_ = new TimerRunnable(eventLoop, milliseconds);
    }

    /**
     * Start the timer running. The timer will expire and generate a signal
     * after the specified delay, unless {@link #stop()} has been called.
     */
    @Override
    public void start() {
        Thread thread = (new Thread(timer_));
        thread.setDaemon(true);
        thread.start();
    }

    /**
     * Cancel the timer. No signal will be generated.
     */
    @Override
    public void stop() {
        timer_.stop();
    }

    @Override
    public String toString() {
        synchronized (timer_) {
            return "JavaTimer for " + timer_.milliseconds_ + 
                    " milliseconds " + 
                    (timer_.running_ ? "running" : "not running"); 
        }
    }
    private final TimerRunnable timer_;
}