aboutsummaryrefslogtreecommitdiffstats
path: root/jrt/src/com/yahoo/jrt/Task.java
blob: a449cd05b4ddc3b4709ff4f05541157f427e8c42 (plain) (blame)
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
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jrt;


/**
 * A Task enables a Runnable to be scheduled for execution in the
 * transport thread some time in the future. Tasks are used internally
 * to handle RPC timeouts. Use the {@link TransportThread#createTask
 * TransportThread.createTask} method to create a task associated with a
 * {@link Transport} object. Note that Task execution is designed to
 * be low-cost, so do not expect extreme accuracy. Also note that any
 * tasks that are pending execution when the owning {@link Transport}
 * object is shut down will never be run.
 **/
public class Task {
    private Scheduler owner;
    private Runnable  doit;
    private int       slot;
    private int       iter;
    private Task      next;
    private Task      prev;
    private boolean   killed;

    // methods used by the scheduler
    int     slot()         { return slot;   }
    void    slot(int val)  { slot = val;    }
    int     iter()         { return iter;   }
    void    iter(int val)  { iter = val;    }
    Task    next()         { return next;   }
    void    next(Task val) { next = val;    }
    Task    prev()         { return prev;   }
    void    prev(Task val) { prev = val;    }
    boolean isKilled()     { return killed; }
    void    setKilled()    { killed = true; }
    void    perform()      { doit.run();    }

    /**
     * Create a Task owned by the given scheduler
     *
     * @param owner the scheduler owning this task
     * @param doit what to run when the task is executed
     **/
    Task(Scheduler owner, Runnable doit) {
        this.owner = owner;
        this.doit = doit;
    }

    /**
     * Schedule this task for execution. A task may be scheduled
     * multiple times, but may only have a single pending execution
     * time. Re-scheduling a task that is not yet run will move the
     * execution time. If the task has already been executed,
     * scheduling works just like if the task was never run.
     *
     * @param seconds the number of seconds until the task should be
     *                executed
     * @see #kill
     **/
    public void schedule(double seconds) {
        owner.schedule(this, seconds);
    }

    /**
     * Schedule this task for execution as soon as possible. This will
     * result in the task being executed the next time the reactor
     * loop inside the owning {@link Transport} object checks for
     * tasks to run. If you have something that is even more urgent,
     * or something you need to be executed even if the {@link
     * Transport} is shut down, use the {@link TransportThread#perform}
     * method instead.
     * @see #kill
     **/
    public void scheduleNow() {
        owner.scheduleNow(this);
    }

    /**
     * Cancel the execution of this task.
     *
     * @return true if the task was scheduled and we managed to avoid
     *         execution
     **/
    public boolean unschedule() {
        return owner.unschedule(this);
    }

    /**
     * Cancel the execution of this task and make sure it can never be
     * scheduled for execution again. After this method is invoked,
     * invoking the {@link #schedule schedule} and {@link #scheduleNow
     * scheduleNow} methods will have no effect.
     *
     * @return true if the task was scheduled and we managed to avoid
     *         execution
     **/
    public boolean kill() {
        return owner.kill(this);
    }
}