#endif
}
-#if defined(__APPLE__) || defined(_MSC_VER)
-#define MAX_STATIC_CONSTRUCTOR_PRIORITY
-#else
-// 101 is the highest priority allowed by the init_priority attribute.
-// This priority is already used by JEMalloc and other memory allocators so
-// we will take the next one.
-#define MAX_STATIC_CONSTRUCTOR_PRIORITY __attribute__ ((__init_priority__(102)))
-#endif
-
-
} // namespace folly
#endif // FOLLY_PORTABILITY_H_
// worry about synchronization with exiting threads.
static bool constructed = (inst_ = new StaticMeta<Tag>());
(void)constructed; // suppress unused warning
-
return *inst_;
}
#endif
static StaticMeta<Tag>* inst_;
- /**
- * We want to disable onThreadExit call at the end of shutdown, we don't care
- * about leaking memory at that point.
- *
- * Otherwise if ThreadLocal is used in a shared library, onThreadExit may be
- * called after dlclose().
- */
- struct PthreadKeyUnregister {
- ~PthreadKeyUnregister() {
- if (inst_) {
- pthread_key_delete(inst_->pthreadKey_);
- }
- }
- };
- static PthreadKeyUnregister pthreadKeyUnregister_;
-
StaticMeta() : nextId_(1) {
head_.next = head_.prev = &head_;
int ret = pthread_key_create(&pthreadKey_, &onThreadExit);
checkPosixError(ret, "pthread_key_create failed");
- (void)pthreadKeyUnregister_; // suppress unused warning
#if FOLLY_HAVE_PTHREAD_ATFORK
ret = pthread_atfork(/*prepare*/ &StaticMeta::preFork,
#endif
template <class Tag> StaticMeta<Tag>* StaticMeta<Tag>::inst_ = nullptr;
-template <class Tag> typename StaticMeta<Tag>::PthreadKeyUnregister
-MAX_STATIC_CONSTRUCTOR_PRIORITY
-StaticMeta<Tag>::pthreadKeyUnregister_;
-
} // namespace threadlocal_detail
} // namespace folly
#include <folly/ThreadLocal.h>
-#include <dlfcn.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <gtest/gtest.h>
#include <folly/Benchmark.h>
-#include <folly/Baton.h>
using namespace folly;
}
}
-TEST(ThreadLocal, SharedLibrary)
-{
- auto handle = dlopen("./_bin/folly/test/lib_thread_local_test.so",
- RTLD_LAZY);
- EXPECT_NE(nullptr, handle);
-
- typedef void (*useA_t)();
- dlerror();
- useA_t useA = (useA_t) dlsym(handle, "useA");
-
- const char *dlsym_error = dlerror();
- EXPECT_EQ(nullptr, dlsym_error);
-
- useA();
-
- folly::Baton<> b11, b12, b21, b22;
-
- std::thread t1([&]() {
- useA();
- b11.post();
- b12.wait();
- });
-
- std::thread t2([&]() {
- useA();
- b21.post();
- b22.wait();
- });
-
- b11.wait();
- b21.wait();
-
- dlclose(handle);
-
- b12.post();
- b22.post();
-
- t1.join();
- t2.join();
-}
-
// clang is unable to compile this code unless in c++14 mode.
#if __cplusplus >= 201402L
namespace {
+++ /dev/null
-/*
- * Copyright 2015 Facebook, 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 <iostream>
-#include <thread>
-
-#include <folly/ThreadLocal.h>
-
-class A {
- public:
- void use() const {
- }
-};
-
-folly::ThreadLocal<A> a;
-
-extern "C" {
-
-void useA() {
- a->use();
-}
-
-}