Initial import
[jpf-core.git] / src / classes / java / lang / ThreadLocal.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package java.lang;
19
20 import gov.nasa.jpf.annotation.NeverBreak;
21 import java.lang.ref.WeakReference;
22 import java.util.Objects;
23 import java.util.function.Supplier;
24
25 /**
26  * model of java.lang.ThreadLocal, which avoids global shared objects
27  * that can otherwise considerably contribute to the state space
28  */
29 public class ThreadLocal<T> {
30
31   static class Entry<E> extends WeakReference<ThreadLocal<E>> {
32     @NeverBreak
33     E val;
34     
35     Entry (ThreadLocal<E> key, E val){
36       super(key);
37       this.val = val;
38     }
39     
40     Entry<E> getChildEntry (){
41       ThreadLocal<E> loc = get();
42       if (loc instanceof InheritableThreadLocal){
43         return new Entry<E>( loc, ((InheritableThreadLocal<E>)loc).childValue(val));
44       } else {
45         return null;
46       }
47     }
48   }
49   
50   public ThreadLocal() {
51   }
52   
53   /**
54    * override to provide initial value 
55    */
56   protected T initialValue() {
57     return null;
58   }
59     
60   private native Entry<T> getEntry();
61   private native void addEntry (Entry<T> e);
62   private native void removeEntry (Entry<T> e);
63   
64   public T get() {
65     Entry<T> e = getEntry();
66     
67     if (e == null){
68       T v = initialValue();
69       e = new Entry<T>(this, v);
70       addEntry(e);
71     }
72     
73     return e.val;
74   }
75   
76   public void set (T v){
77     Entry<T> e = getEntry();
78     
79     if (e != null){
80       e.val = v;
81       
82     } else {
83       e = new Entry<T>(this, v);
84       addEntry(e);      
85     }
86   }
87   
88   public void remove(){
89     Entry<T> e = getEntry();
90     if (e != null){
91       removeEntry(e);
92     }
93   }
94
95   
96   // Java 8 provides this as an internal type to be used from lib classes
97   // ?? why is this not done with overridden initialValue() within the concrete ThreadLocal class
98   static final class SuppliedThreadLocal<E> extends ThreadLocal<E> {
99
100     // we need to preserve the modifiers since this might introduce races (supplier could be shared)
101     private final Supplier<? extends E> sup;
102
103     SuppliedThreadLocal(Supplier<? extends E> supplier) {
104       sup = Objects.requireNonNull(supplier);
105     }
106
107     @Override
108     protected E initialValue() {
109       return sup.get();
110     }
111   }
112 }