3030import java .util .LongSummaryStatistics ;
3131import java .util .Map ;
3232import java .util .Set ;
33- import java .util .Timer ;
34- import java .util .TimerTask ;
3533import java .util .concurrent .CancellationException ;
3634import java .util .concurrent .ConcurrentHashMap ;
3735import java .util .concurrent .Future ;
4644import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
4745import com .oracle .truffle .api .Option ;
4846import com .oracle .truffle .api .TruffleContext ;
47+ import com .oracle .truffle .api .TruffleSafepoint ;
4948import com .oracle .truffle .api .instrumentation .ContextsListener ;
5049import com .oracle .truffle .api .instrumentation .ThreadsListener ;
5150import com .oracle .truffle .api .instrumentation .TruffleInstrument ;
@@ -94,13 +93,6 @@ protected OptionDescriptors getOptionDescriptors() {
9493 return new MemoryUsageInstrumentOptionDescriptors ();
9594 }
9695
97- @ TruffleBoundary
98- public long getContextHeapSize () {
99- TruffleContext context = currentEnv .getEnteredContext ();
100- AtomicBoolean b = new AtomicBoolean ();
101- return currentEnv .calculateContextHeapSize (context , Long .MAX_VALUE , b );
102- }
103-
10496 @ Override
10597 protected synchronized void onCreate (Env env ) {
10698 this .currentEnv = env ;
@@ -202,15 +194,19 @@ Object call(Node node) {
202194 }
203195
204196 tracking .previousProperties = null ;
205- tracking .task = new ContextHeapSizeThreadLocalTask (tracking );
197+ tracking .task = new ContextHeapSizeThreadLocalTask (tracking , 1 );
206198 // force update on start
207199 tracking .task .computeUpdate (true );
208- tracking .timer = new Timer ();
209- tracking .timer .schedule (tracking .task , 0L , 1L );
200+ startWorkerThread (tracking );
210201
211202 return NullValue .NULL ;
212203 }
213204 }
205+
206+ private void startWorkerThread (MemoryTracking tracking ) {
207+ tracking .workerThread = currentEnv .createSystemThread (tracking .task );
208+ tracking .workerThread .start ();
209+ }
214210 }
215211
216212 final class StopContextMemoryTrackingFunction extends BaseFunction {
@@ -223,12 +219,11 @@ Object call(Node node) {
223219 if (tracking .previousProperties != null ) {
224220 return tracking .previousProperties ;
225221 }
226- if (tracking .timer == null ) {
222+ if (tracking .task == null ) {
227223 return NullValue .NULL ;
228224 }
229- tracking .task .cancel ();
230- tracking .timer .cancel ();
231- tracking .timer = null ;
225+
226+ stopWorkerThread (node , tracking );
232227
233228 Map <String , Object > properties = new HashMap <>();
234229
@@ -243,12 +238,20 @@ Object call(Node node) {
243238
244239 // stop running actions for other threads
245240 tracking .previousProperties = new ReadOnlyProperties (properties );
246- tracking .task .cancelled .set (true );
247241 tracking .task = null ;
248242
249243 }
250244 return tracking .previousProperties ;
251245 }
246+
247+ private void stopWorkerThread (Node node , MemoryTracking tracking ) {
248+ // Disable the loop condition so the worker will exit.
249+ tracking .task .stop ();
250+ // Wake the thread in case it's sleeping.
251+ tracking .workerThread .interrupt ();
252+ // Wait until the thread has terminated.
253+ TruffleSafepoint .setBlockedThreadInterruptible (node , Thread ::join , tracking .workerThread );
254+ }
252255 }
253256
254257 static class MemoryTracking {
@@ -257,14 +260,14 @@ static class MemoryTracking {
257260
258261 volatile ContextHeapSizeThreadLocalTask task ;
259262 ReadOnlyProperties previousProperties ;
260- Timer timer ;
263+ Thread workerThread ;
261264
262265 MemoryTracking (TruffleContext context ) {
263266 this .context = context ;
264267 }
265268 }
266269
267- final class ContextHeapSizeThreadLocalTask extends TimerTask {
270+ final class ContextHeapSizeThreadLocalTask implements Runnable {
268271
269272 final LongSummaryStatistics statistics = new LongSummaryStatistics ();
270273 final AtomicBoolean cancelled = new AtomicBoolean ();
@@ -276,14 +279,27 @@ final class ContextHeapSizeThreadLocalTask extends TimerTask {
276279
277280 long totalAllocatedMemory ;
278281 final MemoryTracking tracking ;
282+ final long intervalMillis ;
279283
280- ContextHeapSizeThreadLocalTask (MemoryTracking tracking ) {
284+ ContextHeapSizeThreadLocalTask (MemoryTracking tracking , long intervalMillis ) {
281285 this .tracking = tracking ;
286+ this .intervalMillis = intervalMillis ;
282287 }
283288
284289 @ Override
285290 public void run () {
286- computeUpdate (false );
291+ while (!cancelled .get ()) {
292+ try {
293+ computeUpdate (false );
294+ Thread .sleep (intervalMillis );
295+ } catch (InterruptedException e ) {
296+ break ; // exit the loop if interrupted
297+ }
298+ }
299+ }
300+
301+ public void stop () {
302+ cancelled .set (true );
287303 }
288304
289305 void computeUpdate (boolean force ) {
0 commit comments