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] = {};
+
+} // namespace detail
/**
* Compute the Rabin fingerprint.
#include "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>;
+}
}
};
-#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
#include <folly/Format.h>
#include <folly/ScopeGuard.h>
-DECLARE_ACCESS_SPREADER_TYPE(std::atomic)
-
namespace folly {
namespace detail {
#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
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 {
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*) {
}
};
-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
template <typename dummy> \
struct tag {}; \
} \
- DECLARE_ACCESS_SPREADER_TYPE(tag) \
namespace folly { \
namespace detail { \
template <> \
template <typename dummy> \
struct tag {}; \
} \
- DECLARE_ACCESS_SPREADER_TYPE(tag) \
namespace folly { \
namespace detail { \
template <> \
*/
#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 {
if (tls_sched) {
return tls_sched->scheduler_(n);
}
- return std::rand() % n;
+ return Random::rand32() % n;
}
int DeterministicSchedule::getcpu(unsigned* cpu,
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;