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();
}
```
|