How to pass std :: shared_ptr for callback via unsigned long?

I have an old C-style library that uses a callback with unsigned long for a user argument, and I want to pass my shared_ptr for the callback so that the reference count is incremented.

void callback( unsigned long arg ) {
  std::shared_ptr<my_class> ptr = ??? arg ???
}

void starter_function() {
  std::shared_ptr<my_class> ptr = std::make_shared<my_class>();

  unsigned long arg = ??? ptr ???
  // pass to library so it may be used by callback
}

I am currently using get () on shared_ptr and then using C-style, but this poses a problem when start_function is out of scope.

+4
source share
3 answers

Create static storage (which can be based on std::map<unsigned long, std::shared_ptr<T>>). Provide Functions:

  • register a shared pointer in the repository (which saves it on the map and returns a unique long one).
  • shared_ptr,
  • unsigned long

( ).

, - unsigned long, ( , ), , , , .

: ( , , !)

template typename<T>
class Store
{
    static std::map<unsigned long, std::shared_ptr<T>> store;
    unsigned long h;
    bool contains(unsigned long i)
    {
        return store.find(i) != store.end();
    }
 public:
    unsigned long save(const std::shared_ptr& ptr)
    {
        if (store.size() >= std::numeric_limits<unsigned long>::max())
        {
            // Handle error.  Only possible if 64 bit program with
            // 32 bit unsigned long.
        }
        // find an unused handle.
        do
        {
            ++h;
        } 
        while(contains(h));  // Not a good approach if there are main long-lived objects, and h might wrap.
        // Store and return handle.
        store[h] = ptr;
        return h;
    }

    std::shared_ptr<T> retrieve(unsigned long handle)
    {
       if (!contains(handle))
       {
           // handle error
       }
       const auto result = store[handle];
       store.erase(handle);
       return result;
    }
 };
+9

, "goto" . , .


"" ( - ) , . . , , ( ). , . .


ptr ,

{
    auto sP = make_shared<...>(...);
    thread_start(&sp);
    wait_for_thread_init();
}

void thread_start(std::shared_ptr<...>* ref ) 
    //or unsigned long but you can cast this to a shared_ptr<...>* later.
{
    std::shared_ptr otherPointer = *ref; //here your ref count gets increased
    send_init_complete(); 
    //never use ref from here on. only otherPointer.
}

++ 11 , , .


. , , . , , ..

+1

. , unsigned long , :

  • std::shared_ptr unsigned long .

  • get() .

, shared_ptr; enable_shared_from_this.

, , shared_ptr . :

  1. Make a copy shared_ptrusing new. You will need deleteit after it is no longer needed, and the callback will no longer be used.

If your platform is unsigned longnot large enough to place a pointer, it becomes awkward. The cleanest solution was to keep std::map<unsigned long, std::shared_ptr<...>>around and the counter, which assigns a unique value unsigned longto each shared_ptr, inserts shared_ptrinto the card and passes the card key to the callback.

+1
source

Source: https://habr.com/ru/post/1657751/


All Articles