Refactor thread_id.hpp into cpp and thread_local.hpp

This commit is contained in:
Scott Kyle 2016-06-16 17:02:42 -07:00
parent b55483d2d9
commit 13ab8f8111
7 changed files with 134 additions and 72 deletions

View File

@ -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

View File

@ -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 = "<group>"; };
F64A059F1D13716B004ACDBE /* thread_local.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = thread_local.hpp; sourceTree = "<group>"; };
F67478481CC81F1300F9273C /* platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = platform.cpp; sourceTree = "<group>"; };
F6874A351CAC792D00EEEE36 /* node_types.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = node_types.hpp; sourceTree = "<group>"; };
F6874A3E1CACA5A900EEEE36 /* js_types.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = js_types.hpp; sourceTree = "<group>"; };
@ -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 */,

View File

@ -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": [
"..",

View File

@ -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

View File

@ -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 <atomic>
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<thread_id_t> 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;
}

View File

@ -19,84 +19,17 @@
#ifndef REALM_THREAD_ID_HPP
#define REALM_THREAD_ID_HPP
#include <realm/util/features.h>
#include <atomic>
#if __has_feature(tls) || __has_feature(cxx_thread_local)
#define REALM_HAS_THREAD_LOCAL 1
#else
#define REALM_HAS_THREAD_LOCAL 0
#include <pthread.h>
#endif
#include <cstddef>
namespace realm {
using thread_id_t = std::size_t;
namespace _impl {
#if !REALM_HAS_THREAD_LOCAL
template<typename T>
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<T*>(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<T*>(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<thread_id_t> id_counter;
#if REALM_HAS_THREAD_LOCAL
static REALM_THREAD_LOCAL thread_id_t thread_id = 0;
#else
static _impl::ThreadLocal<thread_id_t> 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

View File

@ -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 <realm/util/features.h>
#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<type>
#include <pthread.h>
namespace realm {
namespace _impl {
template<typename T>
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<T*>(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<T*>(ptr);
});
}
};
} // namespace _impl
} // namespace realm
#endif
#endif // REALM_THREAD_LOCAL_HPP