]> git.basschouten.com Git - openhab-addons.git/blob
4805c1885fea5aaaa45dc7212b9df882fc6dd538
[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      * @throws CloneNotSupportedException
70      */
71     @SuppressWarnings("unchecked")
72     public synchronized AtomicStampedValue<V> copy() {
73         return (AtomicStampedValue<V>) this.clone();
74     }
75
76     /**
77      * Synchronized implementation of clone with exception swallowing
78      */
79     @Override
80     protected synchronized Object clone() {
81         try {
82             return super.clone();
83         } catch (CloneNotSupportedException e) {
84             // We should never end up here since this class implements Cloneable
85             throw new RuntimeException(e);
86         }
87     }
88
89     /**
90      * Copy data atomically if data is after certain stamp ("fresh" enough)
91      *
92      * @param stampMin
93      * @return null, if the stamp of this instance is before stampMin. Otherwise return the data copied
94      */
95     public synchronized @Nullable AtomicStampedValue<V> copyIfStampAfter(long stampMin) {
96         if (stampMin <= this.stamp) {
97             return new AtomicStampedValue<>(this);
98         } else {
99             return null;
100         }
101     }
102
103     /**
104      * Get stamp
105      */
106     public long getStamp() {
107         return stamp;
108     }
109
110     /**
111      * Get value
112      */
113     public V getValue() {
114         return value;
115     }
116
117     /**
118      * Compare two AtomicStampedKeyValue objects based on stamps
119      *
120      * Nulls are ordered first
121      *
122      * @param x first instance
123      * @param y second instance
124      * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater
125      *         than the second.
126      */
127     public static int compare(@SuppressWarnings("rawtypes") @Nullable AtomicStampedValue x,
128             @SuppressWarnings("rawtypes") @Nullable AtomicStampedValue y) {
129         if (x == null) {
130             return -1;
131         } else if (y == null) {
132             return 1;
133         } else {
134             return Long.compare(x.stamp, y.stamp);
135         }
136     }
137 }