about summary refs log tree commit diff
path: root/absl/random
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@google.com>2020-06-17T13·53+0100
committerVincent Ambo <tazjin@google.com>2020-06-17T13·53+0100
commit8f2828c4b4ce502d242eca80a80269448857f4a6 (patch)
treecc3fad62dff6f279ce77f17047c4eef5ebbaf251 /absl/random
parent768eb2ca2857342673fcd462792ce04b8bac3fa3 (diff)
Squashed 'third_party/abseil_cpp/' changes from 768eb2ca2..ccdbb5941
ccdbb5941 Export of internal Abseil changes
01f5f81f9 Export of internal Abseil changes
2c92bdc7c Export of internal Abseil changes
e7ebf9803 Export of internal Abseil changes
2eba343b5 Export of internal Abseil changes
a8b03d90e Export of internal Abseil changes
1d31b5c36 Export of internal Abseil changes
da3a87690 Export of internal Abseil changes
8faf20461 Exclude empty directories (#697)
2069dc796 Export of internal Abseil changes
4832bf6bf Added a BUILD file in root to expose license. (#695)
af8f994af Export of internal Abseil changes
33caf1097 Export of internal Abseil changes
cf1a02e2d Export of internal Abseil changes

git-subtree-dir: third_party/abseil_cpp
git-subtree-split: ccdbb5941f992fabda7eae3ce72f55efc17c826a
Diffstat (limited to 'absl/random')
-rw-r--r--absl/random/BUILD.bazel10
-rw-r--r--absl/random/CMakeLists.txt44
-rw-r--r--absl/random/bit_gen_ref.h107
-rw-r--r--absl/random/bit_gen_ref_test.cc25
-rw-r--r--absl/random/distributions.h2
-rw-r--r--absl/random/internal/BUILD.bazel30
-rw-r--r--absl/random/internal/distribution_caller.h53
-rw-r--r--absl/random/internal/distributions.h52
-rw-r--r--absl/random/internal/mock_helpers.h127
-rw-r--r--absl/random/internal/mock_overload_set.h26
-rw-r--r--absl/random/internal/mocking_bit_gen_base.h85
-rw-r--r--absl/random/internal/uniform_helper.h30
-rw-r--r--absl/random/mock_distributions.h5
-rw-r--r--absl/random/mocking_bit_gen.h178
-rw-r--r--absl/random/seed_sequences_test.cc1
15 files changed, 440 insertions, 335 deletions
diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel
index 9ba75b5236c5..694331c2080d 100644
--- a/absl/random/BUILD.bazel
+++ b/absl/random/BUILD.bazel
@@ -69,7 +69,7 @@ cc_library(
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
-        "//absl/random/internal:distributions",
+        "//absl/random/internal:distribution_caller",
         "//absl/random/internal:fast_uniform_bits",
         "//absl/random/internal:fastmath",
         "//absl/random/internal:generate_real",
@@ -78,7 +78,6 @@ cc_library(
         "//absl/random/internal:uniform_helper",
         "//absl/random/internal:wide_multiply",
         "//absl/strings",
-        "//absl/types:span",
     ],
 )
 
@@ -116,11 +115,12 @@ cc_library(
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":random",
         "//absl/base:core_headers",
+        "//absl/base:fast_type_id",
         "//absl/meta:type_traits",
         "//absl/random/internal:distribution_caller",
         "//absl/random/internal:fast_uniform_bits",
-        "//absl/random/internal:mocking_bit_gen_base",
     ],
 )
 
@@ -146,10 +146,11 @@ cc_library(
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":distributions",
+        ":random",
+        "//absl/base:fast_type_id",
         "//absl/container:flat_hash_map",
         "//absl/meta:type_traits",
         "//absl/random/internal:distribution_caller",
-        "//absl/random/internal:mocking_bit_gen_base",
         "//absl/strings",
         "//absl/types:span",
         "//absl/types:variant",
@@ -411,6 +412,7 @@ cc_test(
     deps = [
         ":bit_gen_ref",
         ":random",
+        "//absl/base:fast_type_id",
         "//absl/random/internal:sequence_urbg",
         "@com_google_googletest//:gtest_main",
     ],
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index ec616dd9526a..ade9ea10f17e 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -45,7 +45,6 @@ absl_cc_library(
     absl::core_headers
     absl::random_internal_distribution_caller
     absl::random_internal_fast_uniform_bits
-    absl::random_internal_mocking_bit_gen_base
     absl::type_traits
 )
 
@@ -62,6 +61,7 @@ absl_cc_test(
     absl::random_bit_gen_ref
     absl::random_random
     absl::random_internal_sequence_urbg
+    absl::fast_type_id
     gmock
     gtest_main
 )
@@ -69,16 +69,16 @@ absl_cc_test(
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
-    random_internal_mocking_bit_gen_base
+    random_internal_mock_helpers
   HDRS
-    "internal/mocking_bit_gen_base.h"
+    "internal/mock_helpers.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::random_random
-    absl::strings
+    absl::fast_type_id
+    absl::optional
 )
 
 # Internal-only target, do not depend on directly.
@@ -93,6 +93,7 @@ absl_cc_library(
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::random_mocking_bit_gen
+    absl::random_internal_mock_helpers
   TESTONLY
 )
 
@@ -111,8 +112,8 @@ absl_cc_library(
     absl::raw_logging_internal
     absl::random_distributions
     absl::random_internal_distribution_caller
-    absl::random_internal_mocking_bit_gen_base
     absl::random_internal_mock_overload_set
+    absl::random_random
     absl::strings
     absl::span
     absl::type_traits
@@ -183,7 +184,7 @@ absl_cc_library(
     absl::config
     absl::core_headers
     absl::random_internal_generate_real
-    absl::random_internal_distributions
+    absl::random_internal_distribution_caller
     absl::random_internal_fast_uniform_bits
     absl::random_internal_fastmath
     absl::random_internal_iostream_state_saver
@@ -191,7 +192,6 @@ absl_cc_library(
     absl::random_internal_uniform_helper
     absl::random_internal_wide_multiply
     absl::strings
-    absl::span
     absl::type_traits
 )
 
@@ -534,27 +534,8 @@ absl_cc_library(
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::config
-)
-
-# Internal-only target, do not depend on directly.
-absl_cc_library(
-  NAME
-    random_internal_distributions
-  HDRS
-    "internal/distributions.h"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  LINKOPTS
-    ${ABSL_DEFAULT_LINKOPTS}
-  DEPS
-    absl::random_internal_distribution_caller
-    absl::random_internal_fast_uniform_bits
-    absl::random_internal_fastmath
-    absl::random_internal_traits
-    absl::random_internal_uniform_helper
-    absl::span
-    absl::strings
-    absl::type_traits
+    absl::utility
+    absl::fast_type_id
 )
 
 # Internal-only target, do not depend on directly.
@@ -745,7 +726,6 @@ absl_cc_library(
     absl::random_internal_salted_seed_seq
     absl::random_internal_seed_material
     absl::span
-    absl::strings
     absl::type_traits
 )
 
@@ -1174,9 +1154,7 @@ absl_cc_library(
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::core_headers
-    absl::random_internal_fast_uniform_bits
-    absl::random_internal_iostream_state_saver
+    absl::config
     absl::random_internal_traits
     absl::type_traits
 )
diff --git a/absl/random/bit_gen_ref.h b/absl/random/bit_gen_ref.h
index 59591a479d8c..9555460fd491 100644
--- a/absl/random/bit_gen_ref.h
+++ b/absl/random/bit_gen_ref.h
@@ -24,11 +24,11 @@
 #ifndef ABSL_RANDOM_BIT_GEN_REF_H_
 #define ABSL_RANDOM_BIT_GEN_REF_H_
 
+#include "absl/base/internal/fast_type_id.h"
 #include "absl/base/macros.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/internal/distribution_caller.h"
 #include "absl/random/internal/fast_uniform_bits.h"
-#include "absl/random/internal/mocking_bit_gen_base.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -51,6 +51,10 @@ struct is_urbg<
         typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
     : std::true_type {};
 
+template <typename>
+struct DistributionCaller;
+class MockHelpers;
+
 }  // namespace random_internal
 
 // -----------------------------------------------------------------------------
@@ -77,23 +81,50 @@ struct is_urbg<
 //    }
 //
 class BitGenRef {
- public:
-  using result_type = uint64_t;
+  // SFINAE to detect whether the URBG type includes a member matching
+  // bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
+  //
+  // These live inside BitGenRef so that they have friend access
+  // to MockingBitGen. (see similar methods in DistributionCaller).
+  template <template <class...> class Trait, class AlwaysVoid, class... Args>
+  struct detector : std::false_type {};
+  template <template <class...> class Trait, class... Args>
+  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
+      : std::true_type {};
+
+  template <class T>
+  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+      std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(),
+      std::declval<void*>()));
+
+  template <typename T>
+  using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
 
-  BitGenRef(const absl::BitGenRef&) = default;
-  BitGenRef(absl::BitGenRef&&) = default;
-  BitGenRef& operator=(const absl::BitGenRef&) = default;
-  BitGenRef& operator=(absl::BitGenRef&&) = default;
+ public:
+  BitGenRef(const BitGenRef&) = default;
+  BitGenRef(BitGenRef&&) = default;
+  BitGenRef& operator=(const BitGenRef&) = default;
+  BitGenRef& operator=(BitGenRef&&) = default;
+
+  template <typename URBG, typename absl::enable_if_t<
+                               (!std::is_same<URBG, BitGenRef>::value &&
+                                random_internal::is_urbg<URBG>::value &&
+                                !HasInvokeMock<URBG>::value)>* = nullptr>
+  BitGenRef(URBG& gen)  // NOLINT
+      : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
+        mock_call_(NotAMock),
+        generate_impl_fn_(ImplFn<URBG>) {}
 
   template <typename URBG,
-            typename absl::enable_if_t<
-                (!std::is_same<URBG, BitGenRef>::value &&
-                 random_internal::is_urbg<URBG>::value)>* = nullptr>
+            typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
+                                        random_internal::is_urbg<URBG>::value &&
+                                        HasInvokeMock<URBG>::value)>* = nullptr>
   BitGenRef(URBG& gen)  // NOLINT
-      : mocked_gen_ptr_(MakeMockPointer(&gen)),
-        t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
-        generate_impl_fn_(ImplFn<URBG>) {
-  }
+      : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
+        mock_call_(&MockCall<URBG>),
+        generate_impl_fn_(ImplFn<URBG>) {}
+
+  using result_type = uint64_t;
 
   static constexpr result_type(min)() {
     return (std::numeric_limits<result_type>::min)();
@@ -106,14 +137,9 @@ class BitGenRef {
   result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); }
 
  private:
-  friend struct absl::random_internal::DistributionCaller<absl::BitGenRef>;
   using impl_fn = result_type (*)(uintptr_t);
-  using mocker_base_t = absl::random_internal::MockingBitGenBase;
-
-  // Convert an arbitrary URBG pointer into either a valid mocker_base_t
-  // pointer or a nullptr.
-  static inline mocker_base_t* MakeMockPointer(mocker_base_t* t) { return t; }
-  static inline mocker_base_t* MakeMockPointer(void*) { return nullptr; }
+  using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*,
+                                void*);
 
   template <typename URBG>
   static result_type ImplFn(uintptr_t ptr) {
@@ -123,29 +149,32 @@ class BitGenRef {
     return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr));
   }
 
-  mocker_base_t* mocked_gen_ptr_;
+  // Get a type-erased InvokeMock pointer.
+  template <typename URBG>
+  static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type,
+                       void* result, void* arg_tuple) {
+    return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result,
+                                                        arg_tuple);
+  }
+  static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) {
+    return false;
+  }
+
+  inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
+                         void* result) {
+    if (mock_call_ == NotAMock) return false;  // avoids an indirect call.
+    return mock_call_(t_erased_gen_ptr_, type, args_tuple, result);
+  }
+
   uintptr_t t_erased_gen_ptr_;
+  mock_call_fn mock_call_;
   impl_fn generate_impl_fn_;
-};
-
-namespace random_internal {
 
-template <>
-struct DistributionCaller<absl::BitGenRef> {
-  template <typename DistrT, typename... Args>
-  static typename DistrT::result_type Call(absl::BitGenRef* gen_ref,
-                                           Args&&... args) {
-    auto* mock_ptr = gen_ref->mocked_gen_ptr_;
-    if (mock_ptr == nullptr) {
-      DistrT dist(std::forward<Args>(args)...);
-      return dist(*gen_ref);
-    } else {
-      return mock_ptr->template Call<DistrT>(std::forward<Args>(args)...);
-    }
-  }
+  template <typename>
+  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock
+  friend class ::absl::random_internal::MockHelpers;          // for InvokeMock
 };
 
-}  // namespace random_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/random/bit_gen_ref_test.cc b/absl/random/bit_gen_ref_test.cc
index ca0e4d707250..1135cf2da0bf 100644
--- a/absl/random/bit_gen_ref_test.cc
+++ b/absl/random/bit_gen_ref_test.cc
@@ -17,30 +17,31 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/internal/fast_type_id.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-class ConstBitGen : public absl::random_internal::MockingBitGenBase {
-  bool CallImpl(const std::type_info&, void*, void* result) override {
+class ConstBitGen {
+ public:
+  // URBG interface
+  using result_type = absl::BitGen::result_type;
+
+  static constexpr result_type(min)() { return (absl::BitGen::min)(); }
+  static constexpr result_type(max)() { return (absl::BitGen::max)(); }
+  result_type operator()() { return 1; }
+
+  // InvokeMock method
+  bool InvokeMock(base_internal::FastTypeIdType index, void*, void* result) {
     *static_cast<int*>(result) = 42;
     return true;
   }
 };
 
-namespace random_internal {
-template <>
-struct DistributionCaller<ConstBitGen> {
-  template <typename DistrT, typename FormatT, typename... Args>
-  static typename DistrT::result_type Call(ConstBitGen* gen, Args&&... args) {
-    return gen->template Call<DistrT, FormatT>(std::forward<Args>(args)...);
-  }
-};
-}  // namespace random_internal
-
 namespace {
+
 int FnTest(absl::BitGenRef gen_ref) { return absl::Uniform(gen_ref, 1, 7); }
 
 template <typename T>
diff --git a/absl/random/distributions.h b/absl/random/distributions.h
index 8680f6a66f0a..6775c5d6ff23 100644
--- a/absl/random/distributions.h
+++ b/absl/random/distributions.h
@@ -57,7 +57,7 @@
 #include "absl/random/beta_distribution.h"
 #include "absl/random/exponential_distribution.h"
 #include "absl/random/gaussian_distribution.h"
-#include "absl/random/internal/distributions.h"  // IWYU pragma: export
+#include "absl/random/internal/distribution_caller.h"  // IWYU pragma: export
 #include "absl/random/internal/uniform_helper.h"  // IWYU pragma: export
 #include "absl/random/log_uniform_int_distribution.h"
 #include "absl/random/poisson_distribution.h"
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index 85d1fb81d23b..d81477ffb7e8 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -45,21 +45,10 @@ cc_library(
     hdrs = ["distribution_caller.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = ["//absl/base:config"],
-)
-
-cc_library(
-    name = "distributions",
-    hdrs = ["distributions.h"],
-    copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        ":distribution_caller",
-        ":traits",
-        ":uniform_helper",
-        "//absl/base",
-        "//absl/meta:type_traits",
-        "//absl/strings",
+        "//absl/base:config",
+        "//absl/base:fast_type_id",
+        "//absl/utility",
     ],
 )
 
@@ -221,7 +210,6 @@ cc_library(
         ":seed_material",
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
-        "//absl/strings",
         "//absl/types:optional",
         "//absl/types:span",
     ],
@@ -497,12 +485,11 @@ cc_test(
 )
 
 cc_library(
-    name = "mocking_bit_gen_base",
-    hdrs = ["mocking_bit_gen_base.h"],
-    linkopts = ABSL_DEFAULT_LINKOPTS,
+    name = "mock_helpers",
+    hdrs = ["mock_helpers.h"],
     deps = [
-        "//absl/random",
-        "//absl/strings",
+        "//absl/base:fast_type_id",
+        "//absl/types:optional",
     ],
 )
 
@@ -511,6 +498,7 @@ cc_library(
     testonly = 1,
     hdrs = ["mock_overload_set.h"],
     deps = [
+        ":mock_helpers",
         "//absl/random:mocking_bit_gen",
         "@com_google_googletest//:gtest",
     ],
@@ -672,6 +660,8 @@ cc_library(
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":traits",
+        "//absl/base:config",
         "//absl/meta:type_traits",
     ],
 )
diff --git a/absl/random/internal/distribution_caller.h b/absl/random/internal/distribution_caller.h
index 4e0724440cbc..fc81b787ebe2 100644
--- a/absl/random/internal/distribution_caller.h
+++ b/absl/random/internal/distribution_caller.h
@@ -20,6 +20,8 @@
 #include <utility>
 
 #include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/utility/utility.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -30,14 +32,57 @@ namespace random_internal {
 // to intercept such calls.
 template <typename URBG>
 struct DistributionCaller {
-  // Call the provided distribution type. The parameters are expected
-  // to be explicitly specified.
-  // DistrT is the distribution type.
+  // SFINAE to detect whether the URBG type includes a member matching
+  // bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
+  //
+  // These live inside BitGenRef so that they have friend access
+  // to MockingBitGen. (see similar methods in DistributionCaller).
+  template <template <class...> class Trait, class AlwaysVoid, class... Args>
+  struct detector : std::false_type {};
+  template <template <class...> class Trait, class... Args>
+  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
+      : std::true_type {};
+
+  template <class T>
+  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+      std::declval<::absl::base_internal::FastTypeIdType>(),
+      std::declval<void*>(), std::declval<void*>()));
+
+  using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
+
+  // Default implementation of distribution caller.
   template <typename DistrT, typename... Args>
-  static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
+  static typename DistrT::result_type Impl(std::false_type, URBG* urbg,
+                                           Args&&... args) {
     DistrT dist(std::forward<Args>(args)...);
     return dist(*urbg);
   }
+
+  // Mock implementation of distribution caller.
+  // The underlying KeyT must match the KeyT constructed by MockOverloadSet.
+  template <typename DistrT, typename... Args>
+  static typename DistrT::result_type Impl(std::true_type, URBG* urbg,
+                                           Args&&... args) {
+    using ResultT = typename DistrT::result_type;
+    using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
+    using KeyT = ResultT(DistrT, ArgTupleT);
+
+    ArgTupleT arg_tuple(std::forward<Args>(args)...);
+    ResultT result;
+    if (!urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
+                          &result)) {
+      auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
+      result = dist(*urbg);
+    }
+    return result;
+  }
+
+  // Default implementation of distribution caller.
+  template <typename DistrT, typename... Args>
+  static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
+    return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,
+                                 std::forward<Args>(args)...);
+  }
 };
 
 }  // namespace random_internal
diff --git a/absl/random/internal/distributions.h b/absl/random/internal/distributions.h
deleted file mode 100644
index d7e3c0161f06..000000000000
--- a/absl/random/internal/distributions.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// 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
-//
-//      https://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 ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
-#define ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
-
-#include <type_traits>
-
-#include "absl/meta/type_traits.h"
-#include "absl/random/internal/distribution_caller.h"
-#include "absl/random/internal/traits.h"
-#include "absl/random/internal/uniform_helper.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace random_internal {
-
-// In the absence of an explicitly provided return-type, the template
-// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
-// the data-types of the endpoint-arguments {A lo, B hi}.
-//
-// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
-// return-type, if one type can be implicitly converted into the other, in a
-// lossless way. The template "is_widening_convertible" implements the
-// compile-time logic for deciding if such a conversion is possible.
-//
-// If no such conversion between {A, B} exists, then the overload for
-// absl::Uniform() will be discarded, and the call will be ill-formed.
-// Return-type for absl::Uniform() when the return-type is inferred.
-template <typename A, typename B>
-using uniform_inferred_return_t =
-    absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
-                                        is_widening_convertible<B, A>>::value,
-                      typename std::conditional<
-                          is_widening_convertible<A, B>::value, B, A>::type>;
-
-}  // namespace random_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
diff --git a/absl/random/internal/mock_helpers.h b/absl/random/internal/mock_helpers.h
new file mode 100644
index 000000000000..9af27ab3a210
--- /dev/null
+++ b/absl/random/internal/mock_helpers.h
@@ -0,0 +1,127 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// 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
+//
+//      https://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 ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
+#define ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
+
+#include <tuple>
+#include <type_traits>
+
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// MockHelpers works in conjunction with MockOverloadSet, MockingBitGen, and
+// BitGenRef to enable the mocking capability for absl distribution functions.
+//
+// MockingBitGen registers mocks based on the typeid of a mock signature, KeyT,
+// which is used to generate a unique id.
+//
+// KeyT is a signature of the form:
+//   result_type(discriminator_type, std::tuple<args...>)
+// The mocked function signature will be composed from KeyT as:
+//   result_type(args...)
+//
+class MockHelpers {
+  using IdType = ::absl::base_internal::FastTypeIdType;
+
+  // Given a key signature type used to index the mock, extract the components.
+  // KeyT is expected to have the form:
+  //   result_type(discriminator_type, arg_tuple_type)
+  template <typename KeyT>
+  struct KeySignature;
+
+  template <typename ResultT, typename DiscriminatorT, typename ArgTupleT>
+  struct KeySignature<ResultT(DiscriminatorT, ArgTupleT)> {
+    using result_type = ResultT;
+    using discriminator_type = DiscriminatorT;
+    using arg_tuple_type = ArgTupleT;
+  };
+
+  // Detector for InvokeMock.
+  template <class T>
+  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+      std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));
+
+  // Empty implementation of InvokeMock.
+  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
+            typename... Args>
+  static absl::optional<ReturnT> InvokeMockImpl(char, URBG*, Args&&...) {
+    return absl::nullopt;
+  }
+
+  // Non-empty implementation of InvokeMock.
+  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
+            typename = invoke_mock_t<URBG>, typename... Args>
+  static absl::optional<ReturnT> InvokeMockImpl(int, URBG* urbg,
+                                                Args&&... args) {
+    ArgTupleT arg_tuple(std::forward<Args>(args)...);
+    ReturnT result;
+    if (urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
+                         &result)) {
+      return result;
+    }
+    return absl::nullopt;
+  }
+
+ public:
+  // Invoke a mock for the KeyT (may or may not be a signature).
+  //
+  // KeyT is used to generate a typeid-based lookup key for the mock.
+  // KeyT is a signature of the form:
+  //   result_type(discriminator_type, std::tuple<args...>)
+  // The mocked function signature will be composed from KeyT as:
+  //   result_type(args...)
+  //
+  // An instance of arg_tuple_type must be constructable from Args..., since
+  // the underlying mechanism requires a pointer to an argument tuple.
+  template <typename KeyT, typename URBG, typename... Args>
+  static auto MaybeInvokeMock(URBG* urbg, Args&&... args)
+      -> absl::optional<typename KeySignature<KeyT>::result_type> {
+    // Use function overloading to dispatch to the implemenation since
+    // more modern patterns (e.g. require + constexpr) are not supported in all
+    // compiler configurations.
+    return InvokeMockImpl<KeyT, typename KeySignature<KeyT>::result_type,
+                          typename KeySignature<KeyT>::arg_tuple_type, URBG>(
+        0, urbg, std::forward<Args>(args)...);
+  }
+
+  // Acquire a mock for the KeyT (may or may not be a signature).
+  //
+  // KeyT is used to generate a typeid-based lookup for the mock.
+  // KeyT is a signature of the form:
+  //   result_type(discriminator_type, std::tuple<args...>)
+  // The mocked function signature will be composed from KeyT as:
+  //   result_type(args...)
+  template <typename KeyT, typename MockURBG>
+  static auto MockFor(MockURBG& m) -> decltype(
+      std::declval<MockURBG>()
+          .template RegisterMock<typename KeySignature<KeyT>::result_type,
+                                 typename KeySignature<KeyT>::arg_tuple_type>(
+              std::declval<IdType>())) {
+    return m.template RegisterMock<typename KeySignature<KeyT>::result_type,
+                                   typename KeySignature<KeyT>::arg_tuple_type>(
+        ::absl::base_internal::FastTypeId<KeyT>());
+  }
+};
+
+}  // namespace random_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
diff --git a/absl/random/internal/mock_overload_set.h b/absl/random/internal/mock_overload_set.h
index c2a30d89d52b..dccc6cee679c 100644
--- a/absl/random/internal/mock_overload_set.h
+++ b/absl/random/internal/mock_overload_set.h
@@ -20,6 +20,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/random/internal/mock_helpers.h"
 #include "absl/random/mocking_bit_gen.h"
 
 namespace absl {
@@ -35,17 +36,20 @@ struct MockSingleOverload;
 // EXPECT_CALL(mock_single_overload, Call(...))` will expand to a call to
 // `mock_single_overload.gmock_Call(...)`. Because expectations are stored on
 // the MockingBitGen (an argument passed inside `Call(...)`), this forwards to
-// arguments to Mocking::Register.
+// arguments to MockingBitGen::Register.
+//
+// The underlying KeyT must match the KeyT constructed by DistributionCaller.
 template <typename DistrT, typename Ret, typename... Args>
 struct MockSingleOverload<DistrT, Ret(MockingBitGen&, Args...)> {
   static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
                 "Overload signature must have return type matching the "
-                "distributions result type.");
+                "distribution result_type.");
+  using KeyT = Ret(DistrT, std::tuple<Args...>);
   auto gmock_Call(
       absl::MockingBitGen& gen,  // NOLINT(google-runtime-references)
-      const ::testing::Matcher<Args>&... args)
-      -> decltype(gen.Register<DistrT, Args...>(args...)) {
-    return gen.Register<DistrT, Args...>(args...);
+      const ::testing::Matcher<Args>&... matchers)
+      -> decltype(MockHelpers::MockFor<KeyT>(gen).gmock_Call(matchers...)) {
+    return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matchers...);
   }
 };
 
@@ -53,13 +57,15 @@ template <typename DistrT, typename Ret, typename Arg, typename... Args>
 struct MockSingleOverload<DistrT, Ret(Arg, MockingBitGen&, Args...)> {
   static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
                 "Overload signature must have return type matching the "
-                "distributions result type.");
+                "distribution result_type.");
+  using KeyT = Ret(DistrT, std::tuple<Arg, Args...>);
   auto gmock_Call(
-      const ::testing::Matcher<Arg>& arg,
+      const ::testing::Matcher<Arg>& matcher,
       absl::MockingBitGen& gen,  // NOLINT(google-runtime-references)
-      const ::testing::Matcher<Args>&... args)
-      -> decltype(gen.Register<DistrT, Arg, Args...>(arg, args...)) {
-    return gen.Register<DistrT, Arg, Args...>(arg, args...);
+      const ::testing::Matcher<Args>&... matchers)
+      -> decltype(MockHelpers::MockFor<KeyT>(gen).gmock_Call(matcher,
+                                                             matchers...)) {
+    return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matcher, matchers...);
   }
 };
 
diff --git a/absl/random/internal/mocking_bit_gen_base.h b/absl/random/internal/mocking_bit_gen_base.h
deleted file mode 100644
index 23ecaf6c7e63..000000000000
--- a/absl/random/internal/mocking_bit_gen_base.h
+++ /dev/null
@@ -1,85 +0,0 @@
-//
-// Copyright 2018 The Abseil Authors.
-//
-// 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
-//
-//      https://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 ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_
-#define ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_
-
-#include <string>
-#include <typeinfo>
-
-#include "absl/random/random.h"
-#include "absl/strings/str_cat.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace random_internal {
-
-class MockingBitGenBase {
-  template <typename>
-  friend struct DistributionCaller;
-  using generator_type = absl::BitGen;
-
- public:
-  // URBG interface
-  using result_type = generator_type::result_type;
-  static constexpr result_type(min)() { return (generator_type::min)(); }
-  static constexpr result_type(max)() { return (generator_type::max)(); }
-  result_type operator()() { return gen_(); }
-
-  virtual ~MockingBitGenBase() = default;
-
- protected:
-  // CallImpl is the type-erased virtual dispatch.
-  // The type of dist is always distribution<T>,
-  // The type of result is always distribution<T>::result_type.
-  virtual bool CallImpl(const std::type_info& distr_type, void* dist_args,
-                        void* result) = 0;
-
-  template <typename DistrT, typename ArgTupleT>
-  static const std::type_info& GetTypeId() {
-    return typeid(std::pair<absl::decay_t<DistrT>, absl::decay_t<ArgTupleT>>);
-  }
-
-  // Call the generating distribution function.
-  // Invoked by DistributionCaller<>::Call<DistT>.
-  // DistT is the distribution type.
-  template <typename DistrT, typename... Args>
-  typename DistrT::result_type Call(Args&&... args) {
-    using distr_result_type = typename DistrT::result_type;
-    using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
-
-    ArgTupleT arg_tuple(std::forward<Args>(args)...);
-    auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
-
-    distr_result_type result{};
-    bool found_match =
-        CallImpl(GetTypeId<DistrT, ArgTupleT>(), &arg_tuple, &result);
-
-    if (!found_match) {
-      result = dist(gen_);
-    }
-
-    return result;
-  }
-
- private:
-  generator_type gen_;
-};  // namespace random_internal
-
-}  // namespace random_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_
diff --git a/absl/random/internal/uniform_helper.h b/absl/random/internal/uniform_helper.h
index 663107cb3a63..5b2afecb89e6 100644
--- a/absl/random/internal/uniform_helper.h
+++ b/absl/random/internal/uniform_helper.h
@@ -19,10 +19,13 @@
 #include <limits>
 #include <type_traits>
 
+#include "absl/base/config.h"
 #include "absl/meta/type_traits.h"
+#include "absl/random/internal/traits.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
+
 template <typename IntType>
 class uniform_int_distribution;
 
@@ -58,6 +61,26 @@ struct IntervalOpenOpenTag
     : public random_internal::TagTypeCompare<IntervalOpenOpenTag> {};
 
 namespace random_internal {
+
+// In the absence of an explicitly provided return-type, the template
+// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
+// the data-types of the endpoint-arguments {A lo, B hi}.
+//
+// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
+// return-type, if one type can be implicitly converted into the other, in a
+// lossless way. The template "is_widening_convertible" implements the
+// compile-time logic for deciding if such a conversion is possible.
+//
+// If no such conversion between {A, B} exists, then the overload for
+// absl::Uniform() will be discarded, and the call will be ill-formed.
+// Return-type for absl::Uniform() when the return-type is inferred.
+template <typename A, typename B>
+using uniform_inferred_return_t =
+    absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
+                                        is_widening_convertible<B, A>>::value,
+                      typename std::conditional<
+                          is_widening_convertible<A, B>::value, B, A>::type>;
+
 // The functions
 //    uniform_lower_bound(tag, a, b)
 // and
@@ -149,12 +172,19 @@ uniform_upper_bound(Tag, FloatType, FloatType b) {
   return std::nextafter(b, (std::numeric_limits<FloatType>::max)());
 }
 
+// UniformDistribution selects either absl::uniform_int_distribution
+// or absl::uniform_real_distribution depending on the NumType parameter.
 template <typename NumType>
 using UniformDistribution =
     typename std::conditional<std::is_integral<NumType>::value,
                               absl::uniform_int_distribution<NumType>,
                               absl::uniform_real_distribution<NumType>>::type;
 
+// UniformDistributionWrapper is used as the underlying distribution type
+// by the absl::Uniform template function. It selects the proper Abseil
+// uniform distribution and provides constructor overloads that match the
+// expected parameter order as well as adjusting distribtuion bounds based
+// on the tag.
 template <typename NumType>
 struct UniformDistributionWrapper : public UniformDistribution<NumType> {
   template <typename TagType>
diff --git a/absl/random/mock_distributions.h b/absl/random/mock_distributions.h
index d36d5ba03cab..764ab370abeb 100644
--- a/absl/random/mock_distributions.h
+++ b/absl/random/mock_distributions.h
@@ -27,6 +27,11 @@
 // More information about the Googletest testing framework is available at
 // https://github.com/google/googletest
 //
+// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
+// the call to absl::Uniform and related methods, otherwise mocking will fail
+// since the  underlying implementation creates a type-specific pointer which
+// will be distinct across different DLL boundaries.
+//
 // Example:
 //
 //   absl::MockingBitGen mock;
diff --git a/absl/random/mocking_bit_gen.h b/absl/random/mocking_bit_gen.h
index 3d8a979e734f..6d2f2c836245 100644
--- a/absl/random/mocking_bit_gen.h
+++ b/absl/random/mocking_bit_gen.h
@@ -33,17 +33,16 @@
 #include <memory>
 #include <tuple>
 #include <type_traits>
-#include <typeindex>
-#include <typeinfo>
 #include <utility>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/internal/fast_type_id.h"
 #include "absl/container/flat_hash_map.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/distributions.h"
 #include "absl/random/internal/distribution_caller.h"
-#include "absl/random/internal/mocking_bit_gen_base.h"
+#include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_join.h"
 #include "absl/types/span.h"
@@ -54,11 +53,12 @@ namespace absl {
 ABSL_NAMESPACE_BEGIN
 
 namespace random_internal {
-
-template <typename, typename>
-struct MockSingleOverload;
+template <typename>
+struct DistributionCaller;
+class MockHelpers;
 
 }  // namespace random_internal
+class BitGenRef;
 
 // MockingBitGen
 //
@@ -96,102 +96,132 @@ struct MockSingleOverload;
 // At this time, only mock distributions supplied within the Abseil random
 // library are officially supported.
 //
-class MockingBitGen : public absl::random_internal::MockingBitGenBase {
+// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
+// the call to absl::Uniform and related methods, otherwise mocking will fail
+// since the  underlying implementation creates a type-specific pointer which
+// will be distinct across different DLL boundaries.
+//
+class MockingBitGen {
  public:
-  MockingBitGen() {}
+  MockingBitGen() = default;
 
-  ~MockingBitGen() override {
+  ~MockingBitGen() {
     for (const auto& del : deleters_) del();
   }
 
+  // URBG interface
+  using result_type = absl::BitGen::result_type;
+
+  static constexpr result_type(min)() { return (absl::BitGen::min)(); }
+  static constexpr result_type(max)() { return (absl::BitGen::max)(); }
+  result_type operator()() { return gen_(); }
+
  private:
-  template <typename DistrT, typename... Args>
-  using MockFnType =
-      ::testing::MockFunction<typename DistrT::result_type(Args...)>;
+  using match_impl_fn = void (*)(void* mock_fn, void* t_erased_arg_tuple,
+                                 void* t_erased_result);
+
+  struct MockData {
+    void* mock_fn = nullptr;
+    match_impl_fn match_impl = nullptr;
+  };
+
+  // GetMockFnType returns the testing::MockFunction for a result and tuple.
+  // This method only exists for type deduction and is otherwise unimplemented.
+  template <typename ResultT, typename... Args>
+  static auto GetMockFnType(ResultT, std::tuple<Args...>)
+      -> ::testing::MockFunction<ResultT(Args...)>;
+
+  // MockFnCaller is a helper method for use with absl::apply to
+  // apply an ArgTupleT to a compatible MockFunction.
+  // NOTE: MockFnCaller is essentially equivalent to the lambda:
+  // [fn](auto... args) { return fn->Call(std::move(args)...)}
+  // however that fails to build on some supported platforms.
+  template <typename ResultT, typename MockFnType, typename Tuple>
+  struct MockFnCaller;
+  // specialization for std::tuple.
+  template <typename ResultT, typename MockFnType, typename... Args>
+  struct MockFnCaller<ResultT, MockFnType, std::tuple<Args...>> {
+    MockFnType* fn;
+    inline ResultT operator()(Args... args) {
+      return fn->Call(std::move(args)...);
+    }
+  };
 
-  // MockingBitGen::Register
+  // MockingBitGen::RegisterMock
   //
-  // Register<DistrT, FormatT, ArgTupleT> is the main extension point for
-  // extending the MockingBitGen framework. It provides a mechanism to install a
-  // mock expectation for the distribution `distr_t` onto the MockingBitGen
-  // context.
+  // RegisterMock<ResultT, ArgTupleT>(FastTypeIdType) is the main extension
+  // point for extending the MockingBitGen framework. It provides a mechanism to
+  // install a mock expectation for a function like ResultT(Args...) keyed by
+  // type_idex onto the MockingBitGen context. The key is that the type_index
+  // used to register must match the type index used to call the mock.
   //
   // The returned MockFunction<...> type can be used to setup additional
   // distribution parameters of the expectation.
-  template <typename DistrT, typename... Args, typename... Ms>
-  decltype(std::declval<MockFnType<DistrT, Args...>>().gmock_Call(
-      std::declval<Ms>()...))
-  Register(Ms&&... matchers) {
-    auto& mock =
-        mocks_[std::type_index(GetTypeId<DistrT, std::tuple<Args...>>())];
-
+  template <typename ResultT, typename ArgTupleT>
+  auto RegisterMock(base_internal::FastTypeIdType type)
+      -> decltype(GetMockFnType(std::declval<ResultT>(),
+                                std::declval<ArgTupleT>()))& {
+    using MockFnType = decltype(
+        GetMockFnType(std::declval<ResultT>(), std::declval<ArgTupleT>()));
+    auto& mock = mocks_[type];
     if (!mock.mock_fn) {
-      auto* mock_fn = new MockFnType<DistrT, Args...>;
+      auto* mock_fn = new MockFnType;
       mock.mock_fn = mock_fn;
-      mock.match_impl = &MatchImpl<DistrT, Args...>;
+      mock.match_impl = &MatchImpl<ResultT, ArgTupleT>;
       deleters_.emplace_back([mock_fn] { delete mock_fn; });
     }
-
-    return static_cast<MockFnType<DistrT, Args...>*>(mock.mock_fn)
-        ->gmock_Call(std::forward<Ms>(matchers)...);
+    return *static_cast<MockFnType*>(mock.mock_fn);
   }
 
-  mutable std::vector<std::function<void()>> deleters_;
-
-  using match_impl_fn = void (*)(void* mock_fn, void* t_erased_dist_args,
-                                 void* t_erased_result);
-  struct MockData {
-    void* mock_fn = nullptr;
-    match_impl_fn match_impl = nullptr;
-  };
-
-  mutable absl::flat_hash_map<std::type_index, MockData> mocks_;
-
-  template <typename DistrT, typename... Args>
-  static void MatchImpl(void* mock_fn, void* dist_args, void* result) {
-    using result_type = typename DistrT::result_type;
-    *static_cast<result_type*>(result) = absl::apply(
-        [mock_fn](Args... args) -> result_type {
-          return (*static_cast<MockFnType<DistrT, Args...>*>(mock_fn))
-              .Call(std::move(args)...);
-        },
-        *static_cast<std::tuple<Args...>*>(dist_args));
+  // MockingBitGen::MatchImpl<> is a dispatch function which converts the
+  // generic type-erased parameters into a specific mock invocation call.
+  // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...>
+  // used to invoke the mock function.
+  // Requires result to point to a ResultT, which is the result of the call.
+  template <typename ResultT, typename ArgTupleT>
+  static void MatchImpl(/*MockFnType<ResultT, Args...>*/ void* mock_fn,
+                        /*ArgTupleT*/ void* args_tuple,
+                        /*ResultT*/ void* result) {
+    using MockFnType = decltype(
+        GetMockFnType(std::declval<ResultT>(), std::declval<ArgTupleT>()));
+    *static_cast<ResultT*>(result) = absl::apply(
+        MockFnCaller<ResultT, MockFnType, ArgTupleT>{
+            static_cast<MockFnType*>(mock_fn)},
+        *static_cast<ArgTupleT*>(args_tuple));
   }
 
-  // Looks for an appropriate mock - Returns the mocked result if one is found.
-  // Otherwise, returns a random value generated by the underlying URBG.
-  bool CallImpl(const std::type_info& key_type, void* dist_args,
-                void* result) override {
+  // MockingBitGen::InvokeMock
+  //
+  // InvokeMock(FastTypeIdType, args, result) is the entrypoint for invoking
+  // mocks registered on MockingBitGen.
+  //
+  // When no mocks are registered on the provided FastTypeIdType, returns false.
+  // Otherwise attempts to invoke the mock function ResultT(Args...) that
+  // was previously registered via the type_index.
+  // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...>
+  // used to invoke the mock function.
+  // Requires result to point to a ResultT, which is the result of the call.
+  inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
+                         void* result) {
     // Trigger a mock, if there exists one that matches `param`.
-    auto it = mocks_.find(std::type_index(key_type));
+    auto it = mocks_.find(type);
     if (it == mocks_.end()) return false;
     auto* mock_data = static_cast<MockData*>(&it->second);
-    mock_data->match_impl(mock_data->mock_fn, dist_args, result);
+    mock_data->match_impl(mock_data->mock_fn, args_tuple, result);
     return true;
   }
 
-  template <typename, typename>
-  friend struct ::absl::random_internal::MockSingleOverload;
-  friend struct ::absl::random_internal::DistributionCaller<
-      absl::MockingBitGen>;
-};
-
-// -----------------------------------------------------------------------------
-// Implementation Details Only Below
-// -----------------------------------------------------------------------------
+  absl::flat_hash_map<base_internal::FastTypeIdType, MockData> mocks_;
+  std::vector<std::function<void()>> deleters_;
+  absl::BitGen gen_;
 
-namespace random_internal {
-
-template <>
-struct DistributionCaller<absl::MockingBitGen> {
-  template <typename DistrT, typename... Args>
-  static typename DistrT::result_type Call(absl::MockingBitGen* gen,
-                                           Args&&... args) {
-    return gen->template Call<DistrT>(std::forward<Args>(args)...);
-  }
+  template <typename>
+  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock
+  friend class ::absl::BitGenRef;                             // for InvokeMock
+  friend class ::absl::random_internal::MockHelpers;  // for RegisterMock,
+                                                      // InvokeMock
 };
 
-}  // namespace random_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/random/seed_sequences_test.cc b/absl/random/seed_sequences_test.cc
index 2cc8b0e6f2b7..fe1100bda0d5 100644
--- a/absl/random/seed_sequences_test.cc
+++ b/absl/random/seed_sequences_test.cc
@@ -96,7 +96,6 @@ template <typename URBG>
 void TestReproducibleVariateSequencesForNonsecureURBG() {
   const size_t kNumVariates = 1000;
 
-  // Master RNG instance.
   URBG rng;
   // Reused for both RNG instances.
   auto reusable_seed = absl::CreateSeedSeqFrom(&rng);