Commit 6c76acfc authored by Eric Niebler's avatar Eric Niebler Committed by Facebook Github Bot 8

folly: fix clang's -Wundefined-var-template

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
parent 7815372b
...@@ -51,12 +51,31 @@ ...@@ -51,12 +51,31 @@
namespace folly { namespace folly {
namespace detail { namespace detail {
template <int BITS> template <int BITS>
struct FingerprintTable { struct FingerprintTable {
static const uint64_t poly[1 + (BITS-1)/64]; static const uint64_t poly[1 + (BITS - 1) / 64];
static const uint64_t table[8][256][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. * Compute the Rabin fingerprint.
......
...@@ -14,9 +14,10 @@ ...@@ -14,9 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
#include "SharedMutex.h" #include <folly/SharedMutex.h>
COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE( namespace folly {
folly::SharedMutexReadPriority); // Explicitly instantiate SharedMutex here:
COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE( template class SharedMutexImpl<true>;
folly::SharedMutexWritePriority); template class SharedMutexImpl<false>;
}
...@@ -1429,16 +1429,33 @@ class SharedMutexImpl { ...@@ -1429,16 +1429,33 @@ class SharedMutexImpl {
} }
}; };
#define COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(type) \ template <
template <> \ bool ReaderPriority,
type::DeferredReaderSlot \ typename Tag_,
type::deferredReaders[type::kMaxDeferredReaders * \ template <typename> class Atom,
type::kDeferredSeparationFactor] = {}; \ bool BlockImmediately>
template <> \ typename SharedMutexImpl<ReaderPriority, Tag_, Atom, BlockImmediately>::
FOLLY_TLS uint32_t type::tls_lastTokenlessSlot = 0; 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<true> SharedMutexReadPriority;
typedef SharedMutexImpl<false> SharedMutexWritePriority; typedef SharedMutexImpl<false> SharedMutexWritePriority;
typedef SharedMutexWritePriority SharedMutex; 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 } // namespace folly
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
#include <folly/Format.h> #include <folly/Format.h>
#include <folly/ScopeGuard.h> #include <folly/ScopeGuard.h>
DECLARE_ACCESS_SPREADER_TYPE(std::atomic)
namespace folly { namespace folly {
namespace detail { namespace detail {
...@@ -233,21 +231,11 @@ Getcpu::Func Getcpu::resolveVdsoFunc() { ...@@ -233,21 +231,11 @@ Getcpu::Func Getcpu::resolveVdsoFunc() {
#ifdef FOLLY_TLS #ifdef FOLLY_TLS
/////////////// SequentialThreadId /////////////// SequentialThreadId
template struct SequentialThreadId<std::atomic>;
template <>
std::atomic<size_t> SequentialThreadId<std::atomic>::prevId(0);
template <>
FOLLY_TLS size_t SequentialThreadId<std::atomic>::currentId(0);
#endif #endif
/////////////// AccessSpreader /////////////// AccessSpreader
template struct AccessSpreader<std::atomic>;
template <>
Getcpu::Func AccessSpreader<std::atomic>::pickGetcpuFunc() {
auto best = Getcpu::resolveVdsoFunc();
return best ? best : &FallbackGetcpuType::getcpu;
}
} // namespace detail } // namespace detail
} // namespace folly } // namespace folly
...@@ -161,6 +161,16 @@ struct SequentialThreadId { ...@@ -161,6 +161,16 @@ struct SequentialThreadId {
static FOLLY_TLS size_t currentId; 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 #endif
struct HashingThreadId { struct HashingThreadId {
...@@ -277,7 +287,10 @@ struct AccessSpreader { ...@@ -277,7 +287,10 @@ struct AccessSpreader {
static bool initialized; static bool initialized;
/// Returns the best getcpu implementation for Atom /// 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 /// Always claims to be on CPU zero, node zero
static int degenerateGetcpu(unsigned* cpu, unsigned* node, void*) { static int degenerateGetcpu(unsigned* cpu, unsigned* node, void*) {
...@@ -326,22 +339,20 @@ struct AccessSpreader { ...@@ -326,22 +339,20 @@ struct AccessSpreader {
} }
}; };
template <> template <template <typename> class Atom>
Getcpu::Func AccessSpreader<std::atomic>::pickGetcpuFunc(); Getcpu::Func AccessSpreader<Atom>::getcpuFunc =
AccessSpreader<Atom>::degenerateGetcpu;
#define DECLARE_ACCESS_SPREADER_TYPE(Atom) \
namespace folly { \ template <template <typename> class Atom>
namespace detail { \ typename AccessSpreader<Atom>::CompactStripe
template <> \ AccessSpreader<Atom>::widthAndCpuToStripe[kMaxCpus + 1][kMaxCpus] = {};
Getcpu::Func AccessSpreader<Atom>::getcpuFunc = \
AccessSpreader<Atom>::degenerateGetcpu; \ template <template <typename> class Atom>
template <> \ bool AccessSpreader<Atom>::initialized = AccessSpreader<Atom>::initialize();
typename AccessSpreader<Atom>::CompactStripe \
AccessSpreader<Atom>::widthAndCpuToStripe[129][128] = {}; \ // Suppress this instantiation in other translation units. It is
template <> \ // instantiated in CacheLocality.cpp
bool AccessSpreader<Atom>::initialized = AccessSpreader<Atom>::initialize(); \ extern template struct AccessSpreader<std::atomic>;
} \
}
} // namespace detail } // namespace detail
} // namespace folly } // namespace folly
...@@ -31,7 +31,6 @@ using namespace folly::detail; ...@@ -31,7 +31,6 @@ using namespace folly::detail;
template <typename dummy> \ template <typename dummy> \
struct tag {}; \ struct tag {}; \
} \ } \
DECLARE_ACCESS_SPREADER_TYPE(tag) \
namespace folly { \ namespace folly { \
namespace detail { \ namespace detail { \
template <> \ template <> \
......
...@@ -413,7 +413,6 @@ TEST(AccessSpreader, Simple) { ...@@ -413,7 +413,6 @@ TEST(AccessSpreader, Simple) {
template <typename dummy> \ template <typename dummy> \
struct tag {}; \ struct tag {}; \
} \ } \
DECLARE_ACCESS_SPREADER_TYPE(tag) \
namespace folly { \ namespace folly { \
namespace detail { \ namespace detail { \
template <> \ template <> \
......
...@@ -15,15 +15,17 @@ ...@@ -15,15 +15,17 @@
*/ */
#include <folly/test/DeterministicSchedule.h> #include <folly/test/DeterministicSchedule.h>
#include <assert.h>
#include <algorithm> #include <algorithm>
#include <list> #include <list>
#include <mutex> #include <mutex>
#include <random> #include <random>
#include <utility>
#include <unordered_map> #include <unordered_map>
#include <assert.h> #include <utility>
DECLARE_ACCESS_SPREADER_TYPE(folly::test::DeterministicAtomic) #include <folly/Random.h>
namespace folly { namespace folly {
namespace test { namespace test {
...@@ -139,7 +141,7 @@ int DeterministicSchedule::getRandNumber(int n) { ...@@ -139,7 +141,7 @@ int DeterministicSchedule::getRandNumber(int n) {
if (tls_sched) { if (tls_sched) {
return tls_sched->scheduler_(n); return tls_sched->scheduler_(n);
} }
return std::rand() % n; return Random::rand32() % n;
} }
int DeterministicSchedule::getcpu(unsigned* cpu, int DeterministicSchedule::getcpu(unsigned* cpu,
......
...@@ -42,11 +42,6 @@ typedef SharedMutexImpl<true, void, DeterministicAtomic, true> ...@@ -42,11 +42,6 @@ typedef SharedMutexImpl<true, void, DeterministicAtomic, true>
typedef SharedMutexImpl<false, void, DeterministicAtomic, true> typedef SharedMutexImpl<false, void, DeterministicAtomic, true>
DSharedMutexWritePriority; DSharedMutexWritePriority;
COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(
DSharedMutexReadPriority);
COMMON_CONCURRENCY_SHARED_MUTEX_DECLARE_STATIC_STORAGE(
DSharedMutexWritePriority);
template <typename Lock> template <typename Lock>
void runBasicTest() { void runBasicTest() {
Lock lock; Lock lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment