boost-ext/di

Shared scope behaves unexpectedly when the injector is a class member

Chaoses-Ib opened this issue · 2 comments

Expected Behavior

When the object where the injector resides is destroyed, the objects created in shared scope by the injector should also be destroyed.

Actual Behavior

Objects in shared scope are not destroyed on destructuring, but only at the end of the process.

Steps to Reproduce the Problem

#include <iostream>
using std::cout;

#include <boost/di.hpp>
#include <boost/di/extension/scopes/shared.hpp>
namespace di = boost::di;

#define CLASS_PRINT(name) \
    name(const name&) { cout << #name " copy\n"; } \
    name(const name&&) { cout << #name " move\n"; } \
    name& operator=(const name&) { cout << #name " operator=\n"; } \
    name& operator=(const name&&) { cout << #name " operator= move\n"; } \
    ~name() { cout << #name " dtor\n"; }

class A {
public:
    A() {
        cout << "A ctor\n";
    }
    CLASS_PRINT(A)
};

class B {
public:
    B(A& a) {
        cout << "B ctor\n";
    }
    CLASS_PRINT(B)
};

class C {
public:
    C(A& a, B b) {
        cout << "C ctor\n";
    }
    CLASS_PRINT(C)
};

class Class1 {
    di::injector<di::extension::shared_config> injector;
public:
    Class1() : injector(di::make_injector<di::extension::shared_config>()) {
        cout << "Class1(){\n";

        C c = injector.create<C>();
        cout << "Class1: C created\n";

        cout << "}\n\n";
    }

    ~Class1() {
        cout << "Class1: ~Class1(){\n";

        cout << "//Why A is not destructured here?\n";
    }
};

void func1(){
    cout << "func1(){\n";

    auto injector = di::make_injector<di::extension::shared_config>();

    C c = injector.create<C>();
    cout << "func1: C created\n";

    cout << "}\n\n";
    
    cout << "{\n";
}

int main()
{
    func1();
    cout << "}\n\n";

    {
        Class1 c1;
    }
    cout << "}\n\n";

    cout << "//The end of main\n";
}

Output:

func1(){
A ctor
B ctor
B move
B dtor
C ctor
B dtor
C move
C dtor
func1: C created
}

{
C dtor
A dtor
}

Class1(){
A ctor
B ctor
B move
B dtor
C ctor
B dtor
C move
C dtor
Class1: C created
}

C dtor
Class1: ~Class1(){
//Why A is not destructured here?
}

//The end of main
A dtor

Specifications

  • Version: 1.2.0
  • Platform: Windows 10 x64
  • Subsystem: MSVC 19.29 x64

di::make_injector(di::bind<A>().in(di::extension::shared)) has the same result.

After a year, I found a solution: change

class Class1 {
    di::injector<di::extension::shared_config> injector;
public:
    Class1() : injector(di::make_injector<di::extension::shared_config>());
};

to

class Class1 {
    di::core::injector<di::extension::shared_config, di::core::pool_t<>> injector;
public:
    Class1() : injector(di::make_injector<di::extension::shared_config>());
};