001 /*
002 * Java Genetic Algorithm Library (jenetics-3.5.0).
003 * Copyright (c) 2007-2016 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.util;
021
022 import java.util.concurrent.atomic.AtomicReference;
023 import java.util.function.Function;
024
025 /**
026 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
027 * @version 2.0
028 * @since 3.0
029 */
030 final class Context<T> {
031
032 private final T _default;
033 private final AtomicReference<Entry<T>> _entry;
034 private final ThreadLocal<Entry<T>> _threadLocalEntry = new ThreadLocal<>();
035
036 Context(final T defaultValue) {
037 _default = defaultValue;
038 _entry = new AtomicReference<>(new Entry<>(defaultValue));
039 }
040
041 void set(final T value) {
042 final Entry<T> e = _threadLocalEntry.get();
043 if (e != null) e.value = value; else _entry.set(new Entry<T>(value));
044 }
045
046 T get() {
047 final Entry<T> e = _threadLocalEntry.get();
048 return (e != null ? e : _entry.get()).value;
049 }
050
051 void reset() {
052 set(_default);
053 }
054
055 <S extends T, R> R with(final S value, final Function<S, R> f) {
056 final Entry<T> e = _threadLocalEntry.get();
057 if (e != null) {
058 _threadLocalEntry.set(e.inner(value));
059 } else {
060 _threadLocalEntry.set(new Entry<T>(value, Thread.currentThread()));
061 }
062
063 try {
064 return f.apply(value);
065 } finally {
066 _threadLocalEntry.set(_threadLocalEntry.get().parent);
067 }
068 }
069
070 /**
071 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
072 * @version 2.0
073 * @since 2.0
074 */
075 private static final class Entry<T> {
076 final Thread thread;
077 final Entry<T> parent;
078 T value;
079
080 Entry(final T value, final Entry<T> parent, final Thread thread) {
081 this.value = value;
082 this.parent = parent;
083 this.thread = thread;
084 }
085
086 Entry(final T value, final Thread thread) {
087 this(value, null, thread);
088 }
089
090 Entry(final T value) {
091 this(value, null, null);
092 }
093
094 Entry<T> inner(final T value) {
095 assert thread == Thread.currentThread();
096 return new Entry<>(value, this, thread);
097 }
098
099 }
100
101 }
|