/*! * Copyright (c) 2015 by Contributors * \file thread_local.h * \brief Common utility for thread local storage. */ #ifndef XGBOOST_COMMON_THREAD_LOCAL_H_ #define XGBOOST_COMMON_THREAD_LOCAL_H_ #if DMLC_ENABLE_STD_THREAD #include #endif #include #include namespace xgboost { namespace common { // macro hanlding for threadlocal variables #ifdef __GNUC__ #define MX_TREAD_LOCAL __thread #elif __STDC_VERSION__ >= 201112L #define MX_TREAD_LOCAL _Thread_local #elif defined(_MSC_VER) #define MX_TREAD_LOCAL __declspec(thread) #endif #ifndef MX_TREAD_LOCAL #message("Warning: Threadlocal is not enabled"); #endif /*! * \brief A threadlocal store to store threadlocal variables. * Will return a thread local singleton of type T * \tparam T the type we like to store */ template class ThreadLocalStore { public: /*! \return get a thread local singleton */ static T* Get() { static MX_TREAD_LOCAL T* ptr = nullptr; if (ptr == nullptr) { ptr = new T(); Singleton()->RegisterDelete(ptr); } return ptr; } private: /*! \brief constructor */ ThreadLocalStore() {} /*! \brief destructor */ ~ThreadLocalStore() { for (size_t i = 0; i < data_.size(); ++i) { delete data_[i]; } } /*! \return singleton of the store */ static ThreadLocalStore *Singleton() { static ThreadLocalStore inst; return &inst; } /*! * \brief register str for internal deletion * \param str the string pointer */ void RegisterDelete(T *str) { #if DMLC_ENABLE_STD_THREAD std::unique_lock lock(mutex_); data_.push_back(str); lock.unlock(); #else data_.push_back(str); #endif } #if DMLC_ENABLE_STD_THREAD /*! \brief internal mutex */ std::mutex mutex_; #endif /*!\brief internal data */ std::vector data_; }; } // namespace common } // namespace xgboost #endif // XGBOOST_COMMON_THREAD_LOCAL_H_