AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified

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:

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.

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