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

Reply via email to