From 13ab8f81118aaea9d303ae7f595f66a50c97e9c2 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 16 Jun 2016 17:02:42 -0700 Subject: [PATCH] Refactor thread_id.hpp into cpp and thread_local.hpp --- react-native/android/src/main/jni/Android.mk | 1 + src/RealmJS.xcodeproj/project.pbxproj | 8 ++ src/node/binding.gyp | 3 +- src/object-store/src/CMakeLists.txt | 7 +- src/object-store/src/util/thread_id.cpp | 37 +++++++++ src/object-store/src/util/thread_id.hpp | 71 +----------------- src/object-store/src/util/thread_local.hpp | 79 ++++++++++++++++++++ 7 files changed, 134 insertions(+), 72 deletions(-) create mode 100644 src/object-store/src/util/thread_id.cpp create mode 100644 src/object-store/src/util/thread_local.hpp diff --git a/react-native/android/src/main/jni/Android.mk b/react-native/android/src/main/jni/Android.mk index a142d3f3..c3637412 100644 --- a/react-native/android/src/main/jni/Android.mk +++ b/react-native/android/src/main/jni/Android.mk @@ -40,6 +40,7 @@ LOCAL_SRC_FILES := \ src/object-store/src/impl/android/external_commit_helper.cpp \ src/object-store/src/impl/android/weak_realm_notifier.cpp \ src/object-store/src/util/format.cpp \ + src/object-store/src/util/thread_id.cpp \ vendor/base64.cpp LOCAL_C_INCLUDES := src diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index 7c77477c..7010bfdd 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -69,6 +69,8 @@ F63FF3261C1642BB00B3B8E0 /* GCDWebServerFileResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F63FF3181C1642BB00B3B8E0 /* GCDWebServerFileResponse.m */; }; F63FF3271C1642BB00B3B8E0 /* GCDWebServerStreamedResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F63FF31A1C1642BB00B3B8E0 /* GCDWebServerStreamedResponse.m */; }; F64A059B1D10D928004ACDBE /* format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E008D21D10AB1B00F3AA37 /* format.cpp */; }; + F64A059D1D13710C004ACDBE /* thread_id.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F64A059C1D13710C004ACDBE /* thread_id.cpp */; }; + F64A059E1D13710C004ACDBE /* thread_id.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F64A059C1D13710C004ACDBE /* thread_id.cpp */; }; F674784A1CC81F1900F9273C /* platform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F67478481CC81F1300F9273C /* platform.cpp */; }; F68A278C1BC2722A0063D40A /* RJSModuleLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */; }; F6BCCFE21C8380A400FE31AE /* lib in Resources */ = {isa = PBXBuildFile; fileRef = F6BCCFDF1C83809A00FE31AE /* lib */; }; @@ -230,6 +232,8 @@ F63FF32C1C16432E00B3B8E0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; F63FF32E1C16433900B3B8E0 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; }; F63FF3301C16434400B3B8E0 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + F64A059C1D13710C004ACDBE /* thread_id.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_id.cpp; sourceTree = ""; }; + F64A059F1D13716B004ACDBE /* thread_local.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = thread_local.hpp; sourceTree = ""; }; F67478481CC81F1300F9273C /* platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = platform.cpp; sourceTree = ""; }; F6874A351CAC792D00EEEE36 /* node_types.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_types.hpp; sourceTree = ""; }; F6874A3E1CACA5A900EEEE36 /* js_types.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = js_types.hpp; sourceTree = ""; }; @@ -365,6 +369,8 @@ 02E008D21D10AB1B00F3AA37 /* format.cpp */, 02E008D31D10AB1B00F3AA37 /* format.hpp */, F6242B291D08EE9600BE1E03 /* thread_id.hpp */, + F64A059C1D13710C004ACDBE /* thread_id.cpp */, + F64A059F1D13716B004ACDBE /* thread_local.hpp */, ); name = util; path = src/util; @@ -790,6 +796,7 @@ F6E931BD1CFEAE370016AF14 /* list_notifier.cpp in Sources */, F60102DA1CBB96C300EC01BA /* shared_realm.cpp in Sources */, F60102E01CBB96D900EC01BA /* realm_coordinator.cpp in Sources */, + F64A059E1D13710C004ACDBE /* thread_id.cpp in Sources */, F60102EA1CBCAFC300EC01BA /* node_dummy.cpp in Sources */, F60102D81CBB96BD00EC01BA /* results.cpp in Sources */, F674784A1CC81F1900F9273C /* platform.cpp in Sources */, @@ -805,6 +812,7 @@ 02E008D51D10ABB600F3AA37 /* format.cpp in Sources */, 02414BA51CE6ABCF00A8669F /* collection_change_builder.cpp in Sources */, 02414BA61CE6ABCF00A8669F /* collection_notifier.cpp in Sources */, + F64A059D1D13710C004ACDBE /* thread_id.cpp in Sources */, 02414BA71CE6ABCF00A8669F /* list_notifier.cpp in Sources */, 02414BA81CE6ABCF00A8669F /* results_notifier.cpp in Sources */, 02414BA91CE6ABCF00A8669F /* collection_notifications.cpp in Sources */, diff --git a/src/node/binding.gyp b/src/node/binding.gyp index 8e322cbb..bc6f65f4 100644 --- a/src/node/binding.gyp +++ b/src/node/binding.gyp @@ -24,7 +24,8 @@ "../object-store/src/impl/node/weak_realm_notifier.cpp", "../object-store/src/parser/parser.cpp", "../object-store/src/parser/query_builder.cpp", - "../object-store/src/util/format.cpp" + "../object-store/src/util/format.cpp", + "../object-store/src/util/thread_id.cpp" ], "include_dirs": [ "..", diff --git a/src/object-store/src/CMakeLists.txt b/src/object-store/src/CMakeLists.txt index 5a0f9f63..13cfc856 100644 --- a/src/object-store/src/CMakeLists.txt +++ b/src/object-store/src/CMakeLists.txt @@ -15,7 +15,8 @@ set(SOURCES impl/transact_log_handler.cpp parser/parser.cpp parser/query_builder.cpp - util/format.cpp) + util/format.cpp + util/thread_id.cpp) set(HEADERS collection_notifications.hpp @@ -39,7 +40,9 @@ set(HEADERS parser/parser.hpp parser/query_builder.hpp util/atomic_shared_ptr.hpp - util/format.hpp) + util/format.hpp + util/thread_id.hpp + util/thread_local.hpp) if(APPLE) list(APPEND SOURCES diff --git a/src/object-store/src/util/thread_id.cpp b/src/object-store/src/util/thread_id.cpp new file mode 100644 index 00000000..6c76adb5 --- /dev/null +++ b/src/object-store/src/util/thread_id.cpp @@ -0,0 +1,37 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// Licensed 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. +// +//////////////////////////////////////////////////////////////////////////// + +#include "thread_id.hpp" +#include "thread_local.hpp" + +#include + +using namespace realm; + +// Since std::thread::id may be reused after a thread is destroyed, we use +// an atomically incremented, thread-local identifier instead. +thread_id_t realm::util::get_thread_id() { + static std::atomic id_counter; + static REALM_THREAD_LOCAL_TYPE(thread_id_t) thread_id = 0; + + if (REALM_UNLIKELY(!thread_id)) { + thread_id = ++id_counter; + } + + return thread_id; +} diff --git a/src/object-store/src/util/thread_id.hpp b/src/object-store/src/util/thread_id.hpp index fc76a328..b3294a04 100644 --- a/src/object-store/src/util/thread_id.hpp +++ b/src/object-store/src/util/thread_id.hpp @@ -19,84 +19,17 @@ #ifndef REALM_THREAD_ID_HPP #define REALM_THREAD_ID_HPP -#include - -#include - -#if __has_feature(tls) || __has_feature(cxx_thread_local) -#define REALM_HAS_THREAD_LOCAL 1 -#else -#define REALM_HAS_THREAD_LOCAL 0 -#include -#endif +#include namespace realm { using thread_id_t = std::size_t; -namespace _impl { - -#if !REALM_HAS_THREAD_LOCAL -template -class ThreadLocal { - public: - ThreadLocal() : m_initial_value() { - init_key(); - } - ThreadLocal(const T &value) : m_initial_value(value) { - init_key(); - } - ~ThreadLocal() { - pthread_key_delete(m_key); - } - - operator T&() { - void* ptr = pthread_getspecific(m_key); - if (!ptr) { - ptr = new T(m_initial_value); - pthread_setspecific(m_key, ptr); - } - return *static_cast(ptr); - } - T& operator=(const T &value) { - T& value_ref = operator T&(); - value_ref = value; - return value_ref; - } - - private: - T m_initial_value; - pthread_key_t m_key; - - void init_key() { - pthread_key_create(&m_key, [](void* ptr) { - delete static_cast(ptr); - }); - } -}; -#endif - -} // namespace _impl - namespace util { // Since std::thread::id may be reused after a thread is destroyed, we use // an atomically incremented, thread-local identifier instead. -inline thread_id_t get_thread_id() { - static std::atomic id_counter; - -#if REALM_HAS_THREAD_LOCAL - static REALM_THREAD_LOCAL thread_id_t thread_id = 0; -#else - static _impl::ThreadLocal thread_id = 0; -#endif - - if (REALM_UNLIKELY(!thread_id)) { - thread_id = ++id_counter; - } - - return thread_id; -} +thread_id_t get_thread_id(); } // namespace util } // namespace realm diff --git a/src/object-store/src/util/thread_local.hpp b/src/object-store/src/util/thread_local.hpp new file mode 100644 index 00000000..89a509af --- /dev/null +++ b/src/object-store/src/util/thread_local.hpp @@ -0,0 +1,79 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// Licensed 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 REALM_THREAD_LOCAL_HPP +#define REALM_THREAD_LOCAL_HPP + +#include + +#if __has_feature(tls) || __has_feature(cxx_thread_local) + +#define REALM_THREAD_LOCAL_TYPE(type) REALM_THREAD_LOCAL type + +#else + +#define REALM_THREAD_LOCAL_TYPE(type) realm::_impl::ThreadLocal + +#include + +namespace realm { +namespace _impl { + +template +class ThreadLocal { + public: + ThreadLocal() : m_initial_value() { + init_key(); + } + ThreadLocal(const T &value) : m_initial_value(value) { + init_key(); + } + ~ThreadLocal() { + pthread_key_delete(m_key); + } + + operator T&() { + void* ptr = pthread_getspecific(m_key); + if (!ptr) { + ptr = new T(m_initial_value); + pthread_setspecific(m_key, ptr); + } + return *static_cast(ptr); + } + T& operator=(const T &value) { + T& value_ref = operator T&(); + value_ref = value; + return value_ref; + } + + private: + T m_initial_value; + pthread_key_t m_key; + + void init_key() { + pthread_key_create(&m_key, [](void* ptr) { + delete static_cast(ptr); + }); + } +}; + +} // namespace _impl +} // namespace realm + +#endif +#endif // REALM_THREAD_LOCAL_HPP