Skip to content

Commit 0cefc0c

Browse files
authored
CPP-924 Pure virtual function called when Session object is being destructed (#483)
Created a smart pointer owning version of `Callback` to ensure that `Cluster` lives as long as `PrepareHostHandler`.
1 parent 3d8c5ab commit 0cefc0c

2 files changed

Lines changed: 30 additions & 2 deletions

File tree

src/callback.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "aligned_storage.hpp"
2121
#include "macros.hpp"
22+
#include "ref_counted.hpp"
2223

2324
#include <new>
2425
#include <stddef.h>
@@ -41,6 +42,14 @@ class Callback {
4142
STATIC_ASSERT(ALIGN_OF(Storage) >= ALIGN_OF(MemberInvoker));
4243
}
4344

45+
template <class F, class T>
46+
Callback(F func, SharedRefPtr<T> ptr)
47+
: invoker_(new (&storage_) MemberPtrInvoker<F, T>(func, ptr)) {
48+
typedef MemberInvoker<F, T> MemberPtrInvoker;
49+
STATIC_ASSERT(sizeof(Storage) >= sizeof(MemberPtrInvoker));
50+
STATIC_ASSERT(ALIGN_OF(Storage) >= ALIGN_OF(MemberPtrInvoker));
51+
}
52+
4453
template <class F>
4554
explicit Callback(F func)
4655
: invoker_(new (&storage_) FunctionInvoker<F>(func)) {
@@ -96,6 +105,20 @@ class Callback {
96105
T* object;
97106
};
98107

108+
template <class F, class T>
109+
struct MemberPtrInvoker : public Invoker {
110+
MemberPtrInvoker(F func, const SharedRefPtr<T>& ptr)
111+
: func(func)
112+
, ptr(ptr) {}
113+
114+
R invoke(const Arg& arg) const { return (ptr.get()->*func)(arg); }
115+
116+
Invoker* copy(Storage* storage) { return new (storage) MemberPtrInvoker<F, T>(func, ptr); }
117+
118+
F func;
119+
SharedRefPtr<T> ptr;
120+
};
121+
99122
template <class F>
100123
struct FunctionInvoker : public Invoker {
101124
FunctionInvoker(F func)
@@ -134,6 +157,11 @@ Callback<R, Arg> bind_callback(R (T::*func)(Arg), T* object) {
134157
return Callback<R, Arg>(func, object);
135158
}
136159

160+
template <class R, class Arg, class T>
161+
Callback<R, Arg> bind_callback(R (T::*func)(Arg), const SharedRefPtr<T>& ptr) {
162+
return Callback<R, Arg>(func, ptr);
163+
}
164+
137165
template <class R, class Arg>
138166
Callback<R, Arg> bind_callback(R (*func)(Arg)) {
139167
return Callback<R, Arg>(func);

src/cluster.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ void Cluster::internal_notify_host_up(const Address& address) {
504504
return; // Ignore host
505505
}
506506

507-
if (!prepare_host(host, bind_callback(&Cluster::on_prepare_host_up, this))) {
507+
if (!prepare_host(host, bind_callback(&Cluster::on_prepare_host_up, Cluster::Ptr(this)))) {
508508
notify_host_up_after_prepare(host);
509509
}
510510
}
@@ -597,7 +597,7 @@ void Cluster::notify_host_add(const Host::Ptr& host) {
597597
return; // Ignore host
598598
}
599599

600-
if (!prepare_host(host, bind_callback(&Cluster::on_prepare_host_add, this))) {
600+
if (!prepare_host(host, bind_callback(&Cluster::on_prepare_host_add, Cluster::Ptr(this)))) {
601601
notify_host_add_after_prepare(host);
602602
}
603603
}

0 commit comments

Comments
 (0)