File size: 2,915 Bytes
985c397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# Function bind_weak



## Usage



* Use `fastsignals::bind_weak` instead of `std::bind` to ensure that nothing happens if method called when binded object already destroyed
* Pass pointer to T class method as first argument, `shared_ptr<T>` or `weak_ptr<T>` as second argument
* Example: `bind_weak(&Document::save(), document, std::placeholders::_1)`, where `document` is a `weak_ptr<Document>` or `shared_ptr<Document>`

## Weak this idiom

The `fastsignals::bind_weak(...)` function implements "weak this" idiom. This idiom helps to avoid dangling pointers and memory access wiolations in asynchronous and/or multithreaded programs.

In the following example, we use weak this idiom to avoid using dangling pointer wehn calling `print()` method of the `Enityt`:

```cpp

struct Entity : std::enable_shared_from_this<Entity>

{

    int value = 42;



    void print()

    {

        std::cout << "print called, num = " << value << std::endl;

    }



    std::function<void()> print_later()

    {

        // ! weak this idiom here !

        auto weak_this = weak_from_this();

        return [weak_this] {

            if (auto shared_this = weak_this.lock())

            {

                shared_this->print();

            }

        };

    }

};



int main()

{

    auto entity = std::make_shared<Entity>();

    auto print = entity->print_later();



    // Prints OK.

    print();



    // Prints nothing - last shared_ptr to the Entity destroyed, so `weak_this.lock()` will return nullptr.

    entity = nullptr;

    print();

}

```

## Using bind_weak to avoid signal receiver lifetime issues



In the following example, `Entity::print()` method connected to the signal. Signal emmited once before and once after the `Entity` instance destroyed. However, no memory access violation happens: once `Entity` destoryed, no slot will be called because `bind_weak` doesn't call binded method if it cannot lock `std::weak_ptr` to binded object. The second `event()` expression just does nothing.



```cpp

#include <fastsignals/signal.h>

#include <fastsignals/bind_weak.h>

#include <iostream>



using VoidSignal = fastsignals::signal<void()>;

using VoidSlot = VoidSignal::slot_type;

struct Entity : std::enable_shared_from_this<Entity>

{

    int value = 42;



    VoidSlot get_print_slot()

    {

        // Here fastsignals::bind_weak() used instead of std::bind.
        return fastsignals::bind_weak(&Entity::print, weak_from_this());

    }


    void print()

    {

        std::cout << "print called, num = " << value << std::endl;

    }

};


int main()
{
    VoidSignal event;

    auto entity = std::make_shared<Entity>();

    event.connect(entity->get_print_slot());


    // Here slot called - it prints `slot called, num = 42`

    event();

    entity = nullptr;


    // Here nothing happens - no exception, no slot call.

    event();

}


```