C++ize BDP estimator, introduce ManualConstructor
diff --git a/src/core/lib/transport/bdp_estimator.h b/src/core/lib/transport/bdp_estimator.h
index 480d523..6b1ebb5 100644
--- a/src/core/lib/transport/bdp_estimator.h
+++ b/src/core/lib/transport/bdp_estimator.h
@@ -19,67 +19,94 @@
 #ifndef GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H
 #define GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H
 
-#include <grpc/support/time.h>
 #include <stdbool.h>
 #include <stdint.h>
+
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 
-#define GRPC_BDP_SAMPLES 16
-#define GRPC_BDP_MIN_SAMPLES_FOR_ESTIMATE 3
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 extern grpc_tracer_flag grpc_bdp_estimator_trace;
 
-typedef enum {
-  GRPC_BDP_PING_UNSCHEDULED,
-  GRPC_BDP_PING_SCHEDULED,
-  GRPC_BDP_PING_STARTED
-} grpc_bdp_estimator_ping_state;
+namespace grpc_core {
 
-typedef struct grpc_bdp_estimator {
-  grpc_bdp_estimator_ping_state ping_state;
-  int64_t accumulator;
-  int64_t estimate;
+class BdpEstimator {
+ public:
+  explicit BdpEstimator(const char *name);
+  ~BdpEstimator();
+
+  // Returns true if a reasonable estimate could be obtained
+  bool EstimateBdp(int64_t *estimate_out) {
+    *estimate_out = estimate_;
+    return true;
+  }
+  bool EstimateBandwidth(double *bw_out) {
+    *bw_out = bw_est_;
+    return true;
+  }
+
+  void AddIncomingBytes(int64_t num_bytes) { accumulator_ += num_bytes; }
+
+  // Returns true if the user should schedule a ping
+  bool NeedPing(grpc_exec_ctx *exec_ctx) {
+    switch (ping_state_) {
+      case PingState::UNSCHEDULED:
+        return grpc_exec_ctx_now(exec_ctx) >= next_ping_scheduled_;
+      case PingState::SCHEDULED:
+      case PingState::STARTED:
+        return false;
+    }
+    GPR_UNREACHABLE_CODE(return false);
+  }
+
+  // Schedule a ping: call in response to receiving a true from
+  // grpc_bdp_estimator_add_incoming_bytes once a ping has been scheduled by a
+  // transport (but not necessarily started)
+  void SchedulePing() {
+    if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
+      gpr_log(GPR_DEBUG, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, name_,
+              accumulator_, estimate_);
+    }
+    GPR_ASSERT(ping_state_ == PingState::UNSCHEDULED);
+    ping_state_ = PingState::SCHEDULED;
+    accumulator_ = 0;
+  }
+
+  // Start a ping: call after calling grpc_bdp_estimator_schedule_ping and
+  // once
+  // the ping is on the wire
+  void StartPing() {
+    if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
+      gpr_log(GPR_DEBUG, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, name_,
+              accumulator_, estimate_);
+    }
+    GPR_ASSERT(ping_state_ == PingState::SCHEDULED);
+    ping_state_ = PingState::STARTED;
+    accumulator_ = 0;
+    ping_start_time_ = gpr_now(GPR_CLOCK_MONOTONIC);
+  }
+
+  // Completes a previously started ping
+  void CompletePing(grpc_exec_ctx *exec_ctx);
+
+ private:
+  enum class PingState { UNSCHEDULED, SCHEDULED, STARTED };
+
+  PingState ping_state_;
+  int64_t accumulator_;
+  int64_t estimate_;
   // when was the current ping started?
-  gpr_timespec ping_start_time;
+  gpr_timespec ping_start_time_;
   // when should the next ping start?
-  grpc_millis next_ping_scheduled;
-  int inter_ping_delay;
-  int stable_estimate_count;
-  double bw_est;
-  const char *name;
-} grpc_bdp_estimator;
+  grpc_millis next_ping_scheduled_;
+  int inter_ping_delay_;
+  int stable_estimate_count_;
+  double bw_est_;
+  const char *name_;
+};
 
-void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name);
+}  // namespace grpc_core
 
-// Returns true if a reasonable estimate could be obtained
-bool grpc_bdp_estimator_get_estimate(const grpc_bdp_estimator *estimator,
-                                     int64_t *estimate);
-// Tracks new bytes read.
-bool grpc_bdp_estimator_get_bw(const grpc_bdp_estimator *estimator, double *bw);
-// Returns true if the user should schedule a ping
-void grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
-                                           int64_t num_bytes);
-// Returns true if the user should schedule a ping
-bool grpc_bdp_estimator_need_ping(grpc_exec_ctx *exec_ctx,
-                                  const grpc_bdp_estimator *estimator);
-// Schedule a ping: call in response to receiving a true from
-// grpc_bdp_estimator_add_incoming_bytes once a ping has been scheduled by a
-// transport (but not necessarily started)
-void grpc_bdp_estimator_schedule_ping(grpc_bdp_estimator *estimator);
-// Start a ping: call after calling grpc_bdp_estimator_schedule_ping and once
-// the ping is on the wire
-void grpc_bdp_estimator_start_ping(grpc_bdp_estimator *estimator);
-// Completes a previously started ping
-void grpc_bdp_estimator_complete_ping(grpc_exec_ctx *exec_ctx,
-                                      grpc_bdp_estimator *estimator);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H */