2 * Copyright (c) 2010-2022 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.automation.jsscripting.internal.threading;
15 import java.time.ZonedDateTime;
16 import java.util.concurrent.TimeUnit;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.openhab.core.model.script.ScriptServiceUtil;
21 import org.openhab.core.model.script.actions.Timer;
22 import org.openhab.core.scheduler.ScheduledCompletableFuture;
23 import org.openhab.core.scheduler.Scheduler;
24 import org.openhab.core.scheduler.SchedulerRunnable;
27 * A replacement for the timer functionality of {@link org.openhab.core.model.script.actions.ScriptExecution
28 * ScriptExecution} which controls multithreaded execution access to the single-threaded GraalJS contexts.
30 * @author Florian Hotze - Initial contribution
32 public class ThreadsafeTimers {
33 private final Object lock;
35 public ThreadsafeTimers(Object lock) {
39 public Timer createTimer(ZonedDateTime instant, Runnable callable) {
40 return createTimer(null, instant, callable);
43 public Timer createTimer(@Nullable String identifier, ZonedDateTime instant, Runnable callable) {
44 Scheduler scheduler = ScriptServiceUtil.getScheduler();
46 return new TimerImpl(scheduler, instant, () -> {
54 public Timer createTimerWithArgument(ZonedDateTime instant, Object arg1, Runnable callable) {
55 return createTimerWithArgument(null, instant, arg1, callable);
58 public Timer createTimerWithArgument(@Nullable String identifier, ZonedDateTime instant, Object arg1,
60 Scheduler scheduler = ScriptServiceUtil.getScheduler();
61 return new TimerImpl(scheduler, instant, () -> {
70 * This is an implementation of the {@link Timer} interface.
71 * Copy of {@link org.openhab.core.model.script.internal.actions.TimerImpl} as this is not accessible from outside
75 * @author Kai Kreuzer - Initial contribution
78 public static class TimerImpl implements Timer {
80 private final Scheduler scheduler;
81 private final ZonedDateTime startTime;
82 private final SchedulerRunnable runnable;
83 private final @Nullable String identifier;
84 private ScheduledCompletableFuture<?> future;
86 public TimerImpl(Scheduler scheduler, ZonedDateTime startTime, SchedulerRunnable runnable) {
87 this(scheduler, startTime, runnable, null);
90 public TimerImpl(Scheduler scheduler, ZonedDateTime startTime, SchedulerRunnable runnable,
91 @Nullable String identifier) {
92 this.scheduler = scheduler;
93 this.startTime = startTime;
94 this.runnable = runnable;
95 this.identifier = identifier;
97 future = scheduler.schedule(runnable, identifier, startTime.toInstant());
101 public boolean cancel() {
102 return future.cancel(true);
106 public synchronized boolean reschedule(ZonedDateTime newTime) {
107 future.cancel(false);
108 future = scheduler.schedule(runnable, identifier, newTime.toInstant());
113 public @Nullable ZonedDateTime getExecutionTime() {
114 return future.isCancelled() ? null : ZonedDateTime.now().plusNanos(future.getDelay(TimeUnit.NANOSECONDS));
118 public boolean isActive() {
119 return !future.isDone();
123 public boolean isCancelled() {
124 return future.isCancelled();
128 public boolean isRunning() {
129 return isActive() && ZonedDateTime.now().isAfter(startTime);
133 public boolean hasTerminated() {
134 return future.isDone();