Make SSEStreamService class public
[netconf.git] / restconf / restconf-nb / src / main / java / org / opendaylight / restconf / nb / rfc8040 / streams / DefaultPingExecutor.java
1 /*
2  * Copyright (c) 2023 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.restconf.nb.rfc8040.streams;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.concurrent.ScheduledFuture;
13 import java.util.concurrent.ScheduledThreadPoolExecutor;
14 import java.util.concurrent.TimeUnit;
15 import java.util.concurrent.atomic.AtomicLong;
16 import javax.annotation.PreDestroy;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.yangtools.concepts.AbstractRegistration;
20 import org.opendaylight.yangtools.concepts.Registration;
21
22 @Singleton
23 public final class DefaultPingExecutor implements PingExecutor, AutoCloseable {
24     private static final class Process extends AbstractRegistration implements Runnable {
25         private final Runnable task;
26         private final ScheduledFuture<?> future;
27
28         Process(final Runnable task, final ScheduledThreadPoolExecutor threadPool, final long delay,
29                 final TimeUnit timeUnit) {
30             this.task = requireNonNull(task);
31             future = threadPool.scheduleWithFixedDelay(task, delay, delay, timeUnit);
32         }
33
34         @Override
35         protected void removeRegistration() {
36             future.cancel(false);
37         }
38
39         @Override
40         public void run() {
41             if (notClosed()) {
42                 task.run();
43             }
44         }
45     }
46
47     public static final String DEFAULT_NAME_PREFIX = "ping-executor";
48     public static final int DEFAULT_CORE_POOL_SIZE = 1;
49
50     // FIXME: Java 21: just use thread-per-task executor with virtual threads
51     private final ScheduledThreadPoolExecutor threadPool;
52
53     public DefaultPingExecutor(final String namePrefix, final int corePoolSize) {
54         final var counter = new AtomicLong();
55         final var group = new ThreadGroup(requireNonNull(namePrefix));
56         threadPool = new ScheduledThreadPoolExecutor(corePoolSize,
57             target -> new Thread(group, target, namePrefix + '-' + counter.incrementAndGet()));
58     }
59
60     @Inject
61     public DefaultPingExecutor() {
62         this(DEFAULT_NAME_PREFIX, DEFAULT_CORE_POOL_SIZE);
63     }
64
65     @Override
66     public Registration startPingProcess(final Runnable task, final long delay, final TimeUnit timeUnit) {
67         return new Process(task, threadPool, delay, timeUnit);
68     }
69
70     @Override
71     @PreDestroy
72     public void close() {
73         threadPool.shutdown();
74     }
75 }