001 /*
002 * Java Genetic Algorithm Library (jenetics-2.0.2).
003 * Copyright (c) 2007-2014 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.internal.util;
021
022 import java.util.concurrent.atomic.AtomicReference;
023
024 import org.jenetics.util.Scoped;
025
026 /**
027 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
028 * @version 2.0 — <em>$Date: 2014-03-15 $</em>
029 * @since 2.0
030 */
031 public final class Context<T> {
032
033 private final T _default;
034 private final AtomicReference<Entry<T>> _entry;
035 private final ThreadLocal<Entry<T>> _threadLocalEntry = new ThreadLocal<>();
036
037 public Context(final T defaultValue) {
038 _default = defaultValue;
039 _entry = new AtomicReference<>(new Entry<>(defaultValue));
040 }
041
042 public void set(final T value) {
043 final Entry<T> e = _threadLocalEntry.get();
044 if (e != null) e.value = value; else _entry.set(new Entry<T>(value));
045 }
046
047 public T get() {
048 final Entry<T> e = _threadLocalEntry.get();
049 return (e != null ? e : _entry.get()).value;
050 }
051
052 public void reset() {
053 set(_default);
054 }
055
056 public <S extends T> Scoped<S> scope(final S value) {
057 final Entry<T> e = _threadLocalEntry.get();
058 if (e != null) {
059 _threadLocalEntry.set(e.inner(value));
060 } else {
061 _threadLocalEntry.set(new Entry<T>(value, Thread.currentThread()));
062 }
063
064 return new Scope<>(value, _threadLocalEntry);
065 }
066
067 public <S> Scoped<S> scope(final T value, final Supplier<? extends S> supplier) {
068 final Scoped<T> scoped = scope(value);
069 return new Scoped<S>() {
070 @Override
071 public S get() {
072 return supplier.get();
073 }
074
075 @Override
076 public void close() {
077 scoped.close();
078 }
079 };
080 }
081
082 /**
083 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
084 * @version 2.0 — <em>$Date: 2014-03-15 $</em>
085 * @since 2.0
086 */
087 private static final class Entry<T> {
088 final Thread thread;
089 final Entry<T> parent;
090
091 T value;
092
093 Entry(final T value, final Entry<T> parent, final Thread thread) {
094 this.value = value;
095 this.parent = parent;
096 this.thread = thread;
097 }
098
099 Entry(final T value, final Thread thread) {
100 this(value, null, thread);
101 }
102
103 Entry(final T value) {
104 this(value, null, null);
105 }
106
107 Entry<T> inner(final T value) {
108 assert(thread == Thread.currentThread());
109 return new Entry<>(value, this, thread);
110 }
111
112 }
113
114 /**
115 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
116 * @version 2.0 — <em>$Date: 2014-03-15 $</em>
117 * @since 2.0
118 */
119 private static final class Scope<A, B> implements Scoped<A> {
120
121 private final A _value;
122 private final ThreadLocal<Entry<B>> _threadLocalEntry;
123
124 Scope(final A value, final ThreadLocal<Entry<B>> threadLocalEntry) {
125 _value = value;
126 _threadLocalEntry = threadLocalEntry;
127 }
128
129 @Override
130 public A get() {
131 return _value;
132 }
133
134 @Override
135 public void close() {
136 final Entry<B> e = _threadLocalEntry.get();
137 if (e != null) {
138 if (e.thread != Thread.currentThread()) {
139 throw new IllegalStateException(
140 "Value context must be closed by the creating thread."
141 );
142 }
143
144 _threadLocalEntry.set(e.parent);
145 } else {
146 throw new IllegalStateException(
147 "Value context has been already close."
148 );
149 }
150 }
151
152 }
153 }
|