47 max_interval = 10000 }; |
47 max_interval = 10000 }; |
48 |
48 |
49 static int num_tasks() { return _num_tasks; } |
49 static int num_tasks() { return _num_tasks; } |
50 |
50 |
51 private: |
51 private: |
52 size_t _counter; |
52 int _counter; |
53 const size_t _interval; |
53 const int _interval; |
54 |
54 |
55 static int _num_tasks; |
55 static int _num_tasks; |
56 static PeriodicTask* _tasks[PeriodicTask::max_tasks]; |
56 static PeriodicTask* _tasks[PeriodicTask::max_tasks]; |
57 static void real_time_tick(size_t delay_time); |
57 static void real_time_tick(int delay_time); |
58 |
58 |
59 #ifndef PRODUCT |
59 #ifndef PRODUCT |
60 static elapsedTimer _timer; // measures time between ticks |
60 static elapsedTimer _timer; // measures time between ticks |
61 static int _ticks; // total number of ticks |
61 static int _ticks; // total number of ticks |
62 static int _intervalHistogram[max_interval]; // to check spacing of timer interrupts |
62 static int _intervalHistogram[max_interval]; // to check spacing of timer interrupts |
67 friend class WatcherThread; |
67 friend class WatcherThread; |
68 public: |
68 public: |
69 PeriodicTask(size_t interval_time); // interval is in milliseconds of elapsed time |
69 PeriodicTask(size_t interval_time); // interval is in milliseconds of elapsed time |
70 ~PeriodicTask(); |
70 ~PeriodicTask(); |
71 |
71 |
72 // Tells whether is enrolled |
|
73 bool is_enrolled() const; |
|
74 |
|
75 // Make the task active |
72 // Make the task active |
76 // NOTE: this may only be called before the WatcherThread has been started |
73 // For dynamic enrollment at the time T, the task will execute somewhere |
|
74 // between T and T + interval_time. |
77 void enroll(); |
75 void enroll(); |
78 |
76 |
79 // Make the task deactive |
77 // Make the task deactive |
80 // NOTE: this may only be called either while the WatcherThread is |
|
81 // inactive or by a task from within its task() method. One-shot or |
|
82 // several-shot tasks may be implemented this way. |
|
83 void disenroll(); |
78 void disenroll(); |
84 |
79 |
85 void execute_if_pending(size_t delay_time) { |
80 void execute_if_pending(int delay_time) { |
86 _counter += delay_time; |
81 // make sure we don't overflow |
87 if (_counter >= _interval) { |
82 jlong tmp = (jlong) _counter + (jlong) delay_time; |
|
83 |
|
84 if (tmp >= (jlong) _interval) { |
88 _counter = 0; |
85 _counter = 0; |
89 task(); |
86 task(); |
|
87 } else { |
|
88 _counter += delay_time; |
90 } |
89 } |
91 } |
90 } |
92 |
91 |
93 // Returns how long (time in milliseconds) before the next time we should |
92 // Returns how long (time in milliseconds) before the next time we should |
94 // execute this task. |
93 // execute this task. |
95 size_t time_to_next_interval() const { |
94 int time_to_next_interval() const { |
96 assert(_interval > _counter, "task counter greater than interval?"); |
95 assert(_interval > _counter, "task counter greater than interval?"); |
97 return _interval - _counter; |
96 return _interval - _counter; |
98 } |
97 } |
99 |
98 |
100 // Calculate when the next periodic task will fire. |
99 // Calculate when the next periodic task will fire. |
101 // Called by the WatcherThread's run method. |
100 // Called by the WatcherThread's run method. |
102 // This assumes that periodic tasks aren't entering the system |
101 static int time_to_wait(); |
103 // dynamically, except for during startup. |
|
104 static size_t time_to_wait() { |
|
105 if (_num_tasks == 0) { |
|
106 // Don't wait any more; shut down the thread since we don't |
|
107 // currently support dynamic enrollment. |
|
108 return 0; |
|
109 } |
|
110 |
|
111 size_t delay = _tasks[0]->time_to_next_interval(); |
|
112 for (int index = 1; index < _num_tasks; index++) { |
|
113 delay = MIN2(delay, _tasks[index]->time_to_next_interval()); |
|
114 } |
|
115 return delay; |
|
116 } |
|
117 |
102 |
118 // The task to perform at each period |
103 // The task to perform at each period |
119 virtual void task() = 0; |
104 virtual void task() = 0; |
120 }; |
105 }; |
121 |
106 |