Hi Christian,
and many thanks for confirming we're not completely off the track.
We have a propagator that has a shared_ptr member. We follow your basic
guidelines and in the propagator dispose function we reset the shared pointer
(decreasing the reference count). On Linux with gcc 4.8 that compiles fine and
behaves as expected. On Windows with Visual Studio 2015 we get a warning:
warning C4265: 'Less': class has virtual functions, but destructor is not
virtual
instances of this class may not be destructed correctly
(and we're living in a "warning-as-errors"-environment).
Would you happen to have some advice on that issue, too?
Many thanks!
Conrad
The example below can be used to reproduce the behavior on Windows (it extends
the naïve Less-constraint from MPG with an otherwise useless shared pointer).
#include <memory>
#include <iostream>
#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/minimodel.hh>
#include <gecode/search.hh>
#include <gecode/kernel.hh>
#include <gecode/support.hh>
using namespace Gecode;
class TestObj{
private:
int i;
public:
TestObj(int i1) : i(i1) {
std::cout << "Constructed" << std::endl;
}
~TestObj(){
std::cout << "Destroyed" << std::endl;
}
};
class Less : public Propagator {
protected:
Int::IntView x0, x1;
std::shared_ptr<TestObj> p;
public:
// posting
Less(Space& home, Int::IntView y0, Int::IntView y1,
std::shared_ptr<TestObj> p1) : Propagator(home), x0(y0), x1(y1) {
x0.subscribe(home,*this,Int::PC_INT_DOM);
x1.subscribe(home,*this,Int::PC_INT_DOM);
p = p1;
home.notice(*this, AP_DISPOSE);
}
static ExecStatus post(Space& home, Int::IntView x0, Int::IntView x1,
std::shared_ptr<TestObj> p) {
(void) new (home) Less(home,x0,x1,p); return ES_OK;
}
// disposal
virtual size_t dispose(Space& home) {
x0.cancel(home,*this,Int::PC_INT_DOM);
x1.cancel(home,*this,Int::PC_INT_DOM);
p.reset();
//p.~shared_ptr<TestObj>();
(void) Propagator::dispose(home);
home.ignore(*this,AP_DISPOSE);
return sizeof(*this);
}
// copying
Less(Space& home, bool share, Less& prop) :
Propagator(home,share,prop), p(prop.p) {
x0.update(home,share,prop.x0);
x1.update(home,share,prop.x1);
}
virtual Propagator* copy(Space& home, bool share) {
return new (home) Less(home,share,*this);
}
// cost computation
virtual PropCost cost(const Space&, const ModEventDelta&) const {
return PropCost::binary(PropCost::LO);
}
// propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta&) {
if (x0.le(home,x1.max()) == Int::ME_INT_FAILED)
return ES_FAILED;
if (x1.gr(home,x0.min()) == Int::ME_INT_FAILED)
return ES_FAILED;
if (x0.assigned() && x1.assigned())
return home.ES_SUBSUMED(*this);
else return ES_NOFIX;
}
};
void less(Space& home, IntVar x0, IntVar x1, std::shared_ptr<TestObj> p) { //
constraint post function
Int::IntView y0(x0), y1(x1);
if (Less::post(home,y0,y1,p) != ES_OK) home.fail();
}
class ExampleSpace : public Script {
protected:
/// Arrays of ints
IntVarArray intvars;
public:
/// Actual model
ExampleSpace(const Options& opt) : Script(opt), intvars(*this,2,0,10) {
std::shared_ptr<TestObj> p = std::make_shared<TestObj>(1);
less(*this,intvars[0],intvars[1],p);
branch(*this, intvars, INT_VAR_SIZE_MIN(), INT_VAL_MIN() );
}
/// Print solution
virtual void
print(std::ostream& os) const {
os << "\t" << intvars << std::endl;
}
/// Constructor for cloning \a s
ExampleSpace(bool share, ExampleSpace& s) : Script(share,s) {
intvars.update(*this, share, s.intvars);
}
/// Copy during cloning
virtual Space*
copy(bool share) {
return new ExampleSpace(true,*this);
}
};
int
main(int argc, char* argv[]) {
Options opt("ExampleSpace");
opt.parse(argc,argv);
Script::run<ExampleSpace,DFS,Options>(opt);
return 0;
}
-----Original Message-----
From: Christian Schulte [mailto:[email protected]]
Sent: Dienstag, 12. April 2016 21:22
To: Drescher, Conrad <[email protected]>; [email protected]
Subject: RE: [gecode-users] Smart pointer in propagator?
Hi Conrad,
There is a catch here: storing a smart pointer (or any other data structure
that has a destructor) in an object is okay, provided that:
1. You register the propagator so that its dispose() member function is
called when the propagator is deleted. But that you say you do.
2. You add an explicit call to the smart pointer's destructor in the
propagator's dispose() function, for example: if p is the smart pointer of
say type unique_ptr<T>, then add p.¨unique_ptr<T>() to the dispose() member
function.
That should do the trick. Is this worth being added as a tip to MPG?
Cheers
Christian
--
Christian Schulte, http://www.gecode.org/~schulte
Professor of Computer Science, KTH, mailto:[email protected]
Expert Researcher, SICS, [email protected]
From: [email protected] [mailto:[email protected]] On Behalf
Of Drescher, Conrad
Sent: Friday, April 8, 2016 14:24
To: [email protected]
Subject: [gecode-users] Smart pointer in propagator?
Hi there,
we were thinking of storing a smart pointer in a propagator that is asking
its home space to call its dispose()-method upon home space deletion. In the
absence of a virtual destructor for class Propagator we're not sure it's a
smart idea. Reading MPG 30.2 did not entirely clarify the situation - could
you please elaborate?
Many thanks!
Conrad
Dr. Conrad Drescher
Senior Developer | AI DEV SCM PLM DE
SAP SE | Dietmar-Hopp-Allee 16 | 69190 Walldorf | Germany
T +49 6227 7-77888 | M +49 160 90684883 | E mailto:[email protected]
http://www.sap.com/
Please consider the impact on the environment before printing this e-mail.
Pflichtangaben/Mandatory Disclosure Statements:
http://www.sap.com/company/legal/impressum.epx
Diese E-Mail kann Betriebs- oder Geschäftsgeheimnisse oder sonstige
vertrauliche Informationen enthalten. Sollten Sie diese E-Mail irrtümlich
erhalten haben, ist Ihnen eine Kenntnisnahme des Inhalts, eine
Vervielfältigung oder Weitergabe der E-Mail ausdrücklich untersagt. Bitte
benachrichtigen Sie uns und vernichten Sie die empfangene E-Mail. Vielen
Dank.
This e-mail may contain trade secrets or privileged, undisclosed, or
otherwise confidential information. If you have received this e-mail in
error, you are hereby notified that any review, copying, or distribution of
it is strictly prohibited. Please inform us immediately and destroy the
original transmittal. Thank you for your cooperation.
_______________________________________________
Gecode users mailing list
[email protected]
https://www.gecode.org/mailman/listinfo/gecode-users