| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef _DECAF_LANG_THREADLOCAL_H_ |
| #define _DECAF_LANG_THREADLOCAL_H_ |
| |
| #include <decaf/util/Config.h> |
| |
| #include <decaf/internal/util/concurrent/ThreadLocalImpl.h> |
| |
| namespace decaf { |
| namespace lang { |
| |
| /** |
| * This class provides thread-local variables. These variables differ from their normal |
| * counterparts in that each thread that accesses one (via its get or set method) has its |
| * own, independently initialized copy of the variable. ThreadLocal instances are typically |
| * private static fields in classes that wish to associate state with a thread (e.g., a |
| * user ID or Transaction ID). This class imposes the restriction on the type that it will |
| * contains that it must by both assignable and copyable. |
| * |
| * Each thread holds an implicit reference to its copy of a thread-local variable as long as |
| * the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, |
| * all of its copies of thread-local instances are destroyed. |
| * |
| * @since 1.0 |
| */ |
| template <typename E> |
| class ThreadLocal : protected decaf::internal::util::concurrent::ThreadLocalImpl { |
| private: |
| |
| ThreadLocal(const ThreadLocal&); |
| ThreadLocal& operator= (const ThreadLocal&); |
| |
| public: |
| |
| /** |
| * Creates a new instance of a ThreadLocal |
| */ |
| ThreadLocal() : ThreadLocalImpl() {} |
| |
| virtual ~ThreadLocal() { |
| try { |
| removeAll(); |
| } catch(...) {} |
| } |
| |
| /** |
| * Returns the value in the current thread's copy of this thread-local variable. If the |
| * variable has no value for the current thread, it is first initialized to the value |
| * returned by an invocation of the initialValue() method. |
| * |
| * @return the current thread's value for this thread local. |
| */ |
| E& get() { |
| void* bytes = getRawValue(); |
| if (bytes == NULL) { |
| E* value = new E(); |
| *value = initialValue(); |
| setRawValue((void*)value); |
| bytes = value; |
| } |
| return *((E*)bytes); |
| } |
| |
| /** |
| * Sets the current thread's copy of this thread-local variable to the specified value. |
| * Most subclasses will have no need to override this method, relying solely on the |
| * initialValue() method to set the values of thread-locals. |
| * |
| * @param value |
| * The new value to assign to this Thread local. |
| */ |
| void set(const E& value) { |
| setRawValue((void*)(new E(value))); |
| } |
| |
| /** |
| * Removes the current thread's value for this thread-local variable. If this thread-local |
| * variable is subsequently read by the current thread, its value will be reinitialized by |
| * invoking its initialValue() method, unless its value is set by the current thread in the |
| * interim. This may result in multiple invocations of the initialValue method in the |
| * current thread. |
| */ |
| void remove() { |
| this->setRawValue(NULL); |
| } |
| |
| protected: |
| |
| /** |
| * Returns the current thread's "initial value" for this thread-local variable. This |
| * method will be invoked the first time a thread accesses the variable with the get() |
| * method, unless the thread previously invoked the set() method, in which case the |
| * initialValue method will not be invoked for the thread. Normally, this method is |
| * invoked at most once per thread, but it may be invoked again in case of subsequent |
| * invocations of remove() followed by get(). |
| * |
| * This implementation simply returns E(); if the programmer desires thread-local |
| * variables to have an initial value other than E(), ThreadLocal must be subclassed, |
| * and this method overridden. Typically, an inner class will be used. |
| * |
| * @param value |
| * Pointer to the thread local value created by this thread when get() is first called. |
| */ |
| virtual E initialValue() const { |
| return E(); |
| } |
| |
| protected: |
| |
| virtual void doDelete(void* value) { |
| if (value != 0) { |
| delete static_cast<E*>(value); |
| } |
| } |
| |
| }; |
| |
| }} |
| |
| #endif /* _DECAF_LANG_THREADLOCAL_H_ */ |