folly: fix clang's -Wundefined-var-template
authorEric Niebler <eniebler@fb.com>
Sat, 25 Jun 2016 18:48:12 +0000 (11:48 -0700)
committerFacebook Github Bot 8 <facebook-github-bot-8-bot@fb.com>
Sat, 25 Jun 2016 18:53:29 +0000 (11:53 -0700)
Summary:
[temp] (14)/6:

> A function template, member function of a class template, variable template, or static data member of a class template shall be defined in every translation unit in which it is implicitly instantiated (14.7.1) unless the corresponding specialization is explicitly instantiated (14.7.2) in some translation unit; no diagnostic is required.

`-Wundefined-var-template` warns on any implicit instantiations that are needed but could not be performed because the definition is not available. In particular, for valid code, this warns on templates/temploids which have their definition and all relevant explicit instantiations tucked away in some source file (but for which no explicit instantiation declarations are provided in the relevant header file) - used a few times in folly. This seems a bad style, the static data member template should either be defined in the header file or should be explicitly instantiated in each .cpp file.

Reviewed By: igorsugak

Differential Revision: D3447679

fbshipit-source-id: 22c90c19e2c7a9b6d772058f2c7e350b890b6c0a

folly/Fingerprint.h
folly/SharedMutex.cpp
folly/SharedMutex.h
folly/detail/CacheLocality.cpp
folly/detail/CacheLocality.h
folly/test/CacheLocalityBenchmark.cpp
folly/test/CacheLocalityTest.cpp
folly/test/DeterministicSchedule.cpp
folly/test/SharedMutexTest.cpp

index f1980ae215aa2b35afe248ad0e60b762fcad7b66..a4400d5ddcb5eb54ce13724e9a77cd3c9db1c30f 100644 (file)
 namespace folly {
 
 namespace detail {
+
 template <int BITS>
 struct FingerprintTable {
-  static const uint64_t poly[1 + (BITS-1)/64];
-  static const uint64_t table[8][256][1 + (BITS-1)/64];
+  static const uint64_t poly[1 + (BITS - 1) / 64];
+  static const uint64_t table[8][256][1 + (BITS - 1) / 64];
 };
-}  // namespace detail
+
+template <int BITS>
+const uint64_t FingerprintTable<BITS>::poly[1 + (BITS - 1) / 64] = {};
+template <int BITS>
+const uint64_t FingerprintTable<BITS>::table[8][256][1 + (BITS - 1) / 64] = {};
+
+#define FOLLY_DECLARE_FINGERPRINT_TABLES(BITS)                      \
+  template <>                                                       \
+  const uint64_t FingerprintTable<BITS>::poly[1 + (BITS - 1) / 64]; \
+  template <>                                                       \
+  const uint64_t FingerprintTable<BITS>::table[8][256][1 + (BITS - 1) / 64]
+
+FOLLY_DECLARE_FINGERPRINT_TABLES(64);
+FOLLY_DECLARE_FINGERPRINT_TABLES(96);
+FOLLY_DECLARE_FINGERPRINT_TABLES(128);
+
+#undef FOLLY_DECLARE_FINGERPRINT_TABLES
+
+} // namespace detail
 
 /**
  * Compute the Rabin fingerprint.
index e7c5267e884fd8c4c8c345fba916c40731a89542..efabaa4e20939c65a38033a36d2a22c6b97aace1 100644 (file)
  * limitations under the License.
  */
 
-#include "SharedMutex.h"
+#include <folly/SharedMutex.h>
 
-COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(
-    folly::SharedMutexReadPriority);
-COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(
-    folly::SharedMutexWritePriority);
+namespace folly {
+// Explicitly instantiate SharedMutex here:
+template class SharedMutexImpl<true>;
+template class SharedMutexImpl<false>;
+}
index 15dc91e6b589378ebb6d20991106156000bfe955..2d71a88473b0f612508181b5172230ef1c13f676 100644 (file)
@@ -1429,16 +1429,33 @@ class SharedMutexImpl {
   }
 };
 
-#define COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(type) \
-  template <>                                                        \
-  type::DeferredReaderSlot                                           \
-      type::deferredReaders[type::kMaxDeferredReaders *              \
-                            type::kDeferredSeparationFactor] = {};   \
-  template <>                                                        \
-  FOLLY_TLS uint32_t type::tls_lastTokenlessSlot = 0;
+template <
+    bool ReaderPriority,
+    typename Tag_,
+    template <typename> class Atom,
+    bool BlockImmediately>
+typename SharedMutexImpl<ReaderPriority, Tag_, Atom, BlockImmediately>::
+    DeferredReaderSlot
+        SharedMutexImpl<ReaderPriority, Tag_, Atom, BlockImmediately>::
+            deferredReaders[kMaxDeferredReaders * kDeferredSeparationFactor] =
+                {};
+
+template <
+    bool ReaderPriority,
+    typename Tag_,
+    template <typename> class Atom,
+    bool BlockImmediately>
+FOLLY_TLS uint32_t
+    SharedMutexImpl<ReaderPriority, Tag_, Atom, BlockImmediately>::
+        tls_lastTokenlessSlot = 0;
 
 typedef SharedMutexImpl<true> SharedMutexReadPriority;
 typedef SharedMutexImpl<false> SharedMutexWritePriority;
 typedef SharedMutexWritePriority SharedMutex;
 
+// Prevent the compiler from instantiating these in other translation units.
+// They are instantiated once in SharedMutex.cpp
+extern template class SharedMutexImpl<true>;
+extern template class SharedMutexImpl<false>;
+
 } // namespace folly
index e75120d6b39c2aa64863ef46a4304461ba4a96d0..c62e0ac8619cda5ce9d250f808319457b1dbc308 100644 (file)
@@ -28,8 +28,6 @@
 #include <folly/Format.h>
 #include <folly/ScopeGuard.h>
 
-DECLARE_ACCESS_SPREADER_TYPE(std::atomic)
-
 namespace folly {
 namespace detail {
 
@@ -233,21 +231,11 @@ Getcpu::Func Getcpu::resolveVdsoFunc() {
 
 #ifdef FOLLY_TLS
 /////////////// SequentialThreadId
-
-template <>
-std::atomic<size_t> SequentialThreadId<std::atomic>::prevId(0);
-
-template <>
-FOLLY_TLS size_t SequentialThreadId<std::atomic>::currentId(0);
+template struct SequentialThreadId<std::atomic>;
 #endif
 
 /////////////// AccessSpreader
-
-template <>
-Getcpu::Func AccessSpreader<std::atomic>::pickGetcpuFunc() {
-  auto best = Getcpu::resolveVdsoFunc();
-  return best ? best : &FallbackGetcpuType::getcpu;
-}
+template struct AccessSpreader<std::atomic>;
 
 } // namespace detail
 } // namespace folly
index 1ede43cbef70b4f60d4f06f40a77890be419dfa1..c9baf5281ac35afb97fd1aea184162a0ede740d0 100644 (file)
@@ -161,6 +161,16 @@ struct SequentialThreadId {
 
   static FOLLY_TLS size_t currentId;
 };
+
+template <template <typename> class Atom>
+Atom<size_t> SequentialThreadId<Atom>::prevId(0);
+
+template <template <typename> class Atom>
+FOLLY_TLS size_t SequentialThreadId<Atom>::currentId(0);
+
+// Suppress this instantiation in other translation units. It is
+// instantiated in CacheLocality.cpp
+extern template struct SequentialThreadId<std::atomic>;
 #endif
 
 struct HashingThreadId {
@@ -277,7 +287,10 @@ struct AccessSpreader {
   static bool initialized;
 
   /// Returns the best getcpu implementation for Atom
-  static Getcpu::Func pickGetcpuFunc();
+  static Getcpu::Func pickGetcpuFunc() {
+    auto best = Getcpu::resolveVdsoFunc();
+    return best ? best : &FallbackGetcpuType::getcpu;
+  }
 
   /// Always claims to be on CPU zero, node zero
   static int degenerateGetcpu(unsigned* cpu, unsigned* node, void*) {
@@ -326,22 +339,20 @@ struct AccessSpreader {
   }
 };
 
-template <>
-Getcpu::Func AccessSpreader<std::atomic>::pickGetcpuFunc();
-
-#define DECLARE_ACCESS_SPREADER_TYPE(Atom)                                     \
-  namespace folly {                                                            \
-  namespace detail {                                                           \
-  template <>                                                                  \
-  Getcpu::Func AccessSpreader<Atom>::getcpuFunc =                              \
-      AccessSpreader<Atom>::degenerateGetcpu;                                  \
-  template <>                                                                  \
-  typename AccessSpreader<Atom>::CompactStripe                                 \
-      AccessSpreader<Atom>::widthAndCpuToStripe[129][128] = {};                \
-  template <>                                                                  \
-  bool AccessSpreader<Atom>::initialized = AccessSpreader<Atom>::initialize(); \
-  }                                                                            \
-  }
+template <template <typename> class Atom>
+Getcpu::Func AccessSpreader<Atom>::getcpuFunc =
+    AccessSpreader<Atom>::degenerateGetcpu;
+
+template <template <typename> class Atom>
+typename AccessSpreader<Atom>::CompactStripe
+    AccessSpreader<Atom>::widthAndCpuToStripe[kMaxCpus + 1][kMaxCpus] = {};
+
+template <template <typename> class Atom>
+bool AccessSpreader<Atom>::initialized = AccessSpreader<Atom>::initialize();
+
+// Suppress this instantiation in other translation units. It is
+// instantiated in CacheLocality.cpp
+extern template struct AccessSpreader<std::atomic>;
 
 } // namespace detail
 } // namespace folly
index 4815cc24cac3be7e9affb0cca99a1284db1ef115..81f094d95111e78dfff894acbd323b611c9ff6ba 100644 (file)
@@ -31,7 +31,6 @@ using namespace folly::detail;
   template <typename dummy>                            \
   struct tag {};                                       \
   }                                                    \
-  DECLARE_ACCESS_SPREADER_TYPE(tag)                    \
   namespace folly {                                    \
   namespace detail {                                   \
   template <>                                          \
index 9c326fde4ba320b7f88b198ee8fc5ac8d695da8b..33af739bd626c916702e881310553b596f11c292 100644 (file)
@@ -413,7 +413,6 @@ TEST(AccessSpreader, Simple) {
   template <typename dummy>                            \
   struct tag {};                                       \
   }                                                    \
-  DECLARE_ACCESS_SPREADER_TYPE(tag)                    \
   namespace folly {                                    \
   namespace detail {                                   \
   template <>                                          \
index fe59cc02145c47357fb68158a16914119a9cb634..f7668fc587e5bd68d9270683f3b2e0c8007bafc8 100644 (file)
  */
 
 #include <folly/test/DeterministicSchedule.h>
+
+#include <assert.h>
+
 #include <algorithm>
 #include <list>
 #include <mutex>
 #include <random>
-#include <utility>
 #include <unordered_map>
-#include <assert.h>
+#include <utility>
 
-DECLARE_ACCESS_SPREADER_TYPE(folly::test::DeterministicAtomic)
+#include <folly/Random.h>
 
 namespace folly {
 namespace test {
@@ -139,7 +141,7 @@ int DeterministicSchedule::getRandNumber(int n) {
   if (tls_sched) {
     return tls_sched->scheduler_(n);
   }
-  return std::rand() % n;
+  return Random::rand32() % n;
 }
 
 int DeterministicSchedule::getcpu(unsigned* cpu,
index 8672e665d1ba54412c4c8547e84d37f8824d9b12..98df9d09cbde1fe0f7da6248d03511fcf6348e3f 100644 (file)
@@ -42,11 +42,6 @@ typedef SharedMutexImpl<true, void, DeterministicAtomic, true>
 typedef SharedMutexImpl<false, void, DeterministicAtomic, true>
     DSharedMutexWritePriority;
 
-COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(
-    DSharedMutexReadPriority);
-COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(
-    DSharedMutexWritePriority);
-
 template <typename Lock>
 void runBasicTest() {
   Lock lock;