]> git.basschouten.com Git - openhab-addons.git/blob
98099e668fc5c501d3889ed3dbf80e2b693e74b2
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.modbus.internal;
14
15 import java.util.Objects;
16
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19
20 /**
21  * Timestamp-value pair that can be updated atomically
22  *
23  * @author Sami Salonen - Initial contribution
24  *
25  * @param <V> type of the value
26  */
27 @NonNullByDefault
28 public class AtomicStampedValue<V> implements Cloneable {
29
30     private long stamp;
31     private V value;
32
33     private AtomicStampedValue(AtomicStampedValue<V> copy) {
34         this(copy.stamp, copy.value);
35     }
36
37     /**
38      * Construct new stamped key-value pair
39      *
40      * @param stamp stamp for the data
41      * @param value value for the data
42      *
43      * @throws NullPointerException when key or value is null
44      */
45     public AtomicStampedValue(long stamp, V value) {
46         Objects.requireNonNull(value, "value should not be null!");
47         this.stamp = stamp;
48         this.value = value;
49     }
50
51     /**
52      * Update data in this instance atomically
53      *
54      * @param stamp stamp for the data
55      * @param value value for the data
56      *
57      * @throws NullPointerException when value is null
58      */
59     public synchronized void update(long stamp, V value) {
60         Objects.requireNonNull(value, "value should not be null!");
61         this.stamp = stamp;
62         this.value = value;
63     }
64
65     /**
66      * Copy data atomically and return the new (shallow) copy
67      *
68      * @return new copy of the data
69      */
70     @SuppressWarnings("unchecked")
71     public synchronized AtomicStampedValue<V> copy() {
72         return (AtomicStampedValue<V>) this.clone();
73     }
74
75     /**
76      * Synchronized implementation of clone with exception swallowing
77      */
78     @Override
79     protected synchronized Object clone() {
80         try {
81             return super.clone();
82         } catch (CloneNotSupportedException e) {
83             // We should never end up here since this class implements Cloneable
84             throw new RuntimeException(e);
85         }
86     }
87
88     /**
89      * Copy data atomically if data is after certain stamp ("fresh" enough)
90      *
91      * @param stampMin
92      * @return null, if the stamp of this instance is before stampMin. Otherwise return the data copied
93      */
94     public synchronized @Nullable AtomicStampedValue<V> copyIfStampAfter(long stampMin) {
95         if (stampMin <= this.stamp) {
96             return new AtomicStampedValue<>(this);
97         } else {
98             return null;
99         }
100     }
101
102     /**
103      * Get stamp
104      */
105     public long getStamp() {
106         return stamp;
107     }
108
109     /**
110      * Get value
111      */
112     public V getValue() {
113         return value;
114     }
115
116     /**
117      * Compare two AtomicStampedKeyValue objects based on stamps
118      *
119      * Nulls are ordered first
120      *
121      * @param x first instance
122      * @param y second instance
123      * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater
124      *         than the second.
125      */
126     public static int compare(@SuppressWarnings("rawtypes") @Nullable AtomicStampedValue x,
127             @SuppressWarnings("rawtypes") @Nullable AtomicStampedValue y) {
128         if (x == null) {
129             return -1;
130         } else if (y == null) {
131             return 1;
132         } else {
133             return Long.compare(x.stamp, y.stamp);
134         }
135     }
136 }