| /** |
| * 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 QUICKSTEP_THREADING_THREAD_ID_BASED_MAP_HPP_ |
| #define QUICKSTEP_THREADING_THREAD_ID_BASED_MAP_HPP_ |
| |
| #include <unordered_map> |
| |
| #include "threading/ThreadingConfig.h" |
| |
| #ifdef QUICKSTEP_HAVE_POSIX_THREADS |
| #include <pthread.h> |
| #endif |
| |
| #ifdef QUICKSTEP_HAVE_CPP11_THREADS |
| #include <thread> // NOLINT(build/c++11) |
| #endif |
| |
| #ifdef QUICKSTEP_HAVE_WINDOWS_THREADS |
| #include "threading/WinThreadsAPI.hpp" |
| #endif |
| |
| #include "storage/StorageConstants.hpp" |
| #include "threading/Mutex.hpp" |
| #include "threading/SharedMutex.hpp" |
| #include "threading/SpinSharedMutex.hpp" |
| #include "utility/Macros.hpp" |
| |
| #include "glog/logging.h" |
| |
| namespace quickstep { |
| |
| /** \addtogroup Threading |
| * @{ |
| */ |
| /** |
| * @brief A map which uses caller thread's ID as a key based on a singleton |
| * pattern. |
| * |
| * @note This is in a way a simulation of thread-local object storage. |
| **/ |
| template <class V, char... name> |
| class ThreadIDBasedMap { |
| public: |
| #ifdef QUICKSTEP_HAVE_CPP11_THREADS |
| typedef std::thread::id thread_id_t; |
| #endif |
| #ifdef QUICKSTEP_HAVE_POSIX_THREADS |
| typedef pthread_t thread_id_t; |
| #endif |
| #ifdef QUICKSTEP_HAVE_WINDOWS_THREADS |
| typedef DWORD thread_id_t; |
| #endif |
| /** |
| * @brief Get the instance of the map. |
| * |
| * @warning The initialization of the instance is not thread safe. |
| * |
| * @return A pointer to the instance. |
| **/ |
| static ThreadIDBasedMap* Instance() { |
| static ThreadIDBasedMap instance; |
| return &instance; |
| } |
| |
| /** |
| * @brief Add a value to the map. |
| * |
| * @param value The value to be added. |
| **/ |
| void addValue(const V &value) { |
| const thread_id_t key = getKey(); |
| { |
| SpinSharedMutexExclusiveLock<false> lock(map_mutex_); |
| DCHECK(map_.find(key) == map_.end()); |
| map_[key] = value; |
| } |
| } |
| |
| /** |
| * @brief Remove the value for the caller thread. |
| **/ |
| void removeValue() { |
| const thread_id_t key = getKey(); |
| { |
| SpinSharedMutexExclusiveLock<false> lock(map_mutex_); |
| // Use the following way to avoid exception in erase() call. |
| auto remove_iter = map_.find(key); |
| DCHECK(remove_iter != map_.end()); |
| map_.erase(remove_iter); |
| } |
| } |
| |
| /** |
| * @brief Get the value corresponding to the caller thread. |
| * |
| * @return The value for which the key is the caller thread's ID. |
| **/ |
| const V& getValue() const { |
| const thread_id_t key = getKey(); |
| { |
| SpinSharedMutexSharedLock<false> lock(map_mutex_); |
| const auto it = map_.find(key); |
| DCHECK(it != map_.end()); |
| return it->second; |
| } |
| } |
| |
| private: |
| /** |
| * @brief Constructor. |
| **/ |
| ThreadIDBasedMap() {} |
| |
| /** |
| * @brief Destructor. |
| * |
| * @note The destructor is private in order to prevent any caller that holds |
| * a pointer to the map from accidentally deleting it. |
| **/ |
| ~ThreadIDBasedMap() {} |
| |
| /** |
| * @brief Return a unique key corresponding to the caller thread. |
| * |
| * @return A unique key. |
| **/ |
| static thread_id_t getKey() { |
| #ifdef QUICKSTEP_HAVE_CPP11_THREADS |
| return std::this_thread::get_id(); |
| #endif |
| #ifdef QUICKSTEP_HAVE_POSIX_THREADS |
| return pthread_self(); |
| #endif |
| #ifdef QUICKSTEP_HAVE_WINDOWS_THREADS |
| return GetCurrentThreadId(); |
| #endif |
| } |
| |
| std::unordered_map<thread_id_t, V> map_; |
| |
| alignas(kCacheLineBytes) mutable SpinSharedMutex<false> map_mutex_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ThreadIDBasedMap); |
| }; |
| |
| /** @} */ |
| |
| } // namespace quickstep |
| |
| #endif // QUICKSTEP_THREADING_THREAD_ID_BASED_MAP_HPP_ |