1

I have program that receives callback calls from a library when messages are received. The callbacks' signature is void on_message(const MyLargeObject &my_large_object);

My code for reacting to some of the messages is more complex than what I want to run directly in the callbacks. Because of that, I am launching an asynchronous task (std::async) to do the actual processing.

Currently, the asynchronous tasks' signature is void on_message_async_task(MyLargeObject my_large_object);. My reasoning says that I should pass the argument to the async task as a copy because I see no guarantee that the original object lives until the task is finished. Static code analysis is, however, saying that I should use const reference instead to avoid expensive copying. Is that false positive or am I missing something here?

10
  • 2
    The static code analysis is giving a suggestion. It's suggestion does not seem appropriate in this situation. If you really want to placate the static code analyzer, consider passing void on_message(std::unique_ptr<MyLargeObject> my_large_object_in_a_smart_pointer). Commented Dec 2, 2024 at 15:13
  • Using a smart pointer will ensure the lifetime of the object, as well as save copying. Commented Dec 2, 2024 at 15:15
  • I can't change the signature of the callback. Because of that, as far as I know, I can't use a smart pointer to avoid copying. Commented Dec 2, 2024 at 15:28
  • There is a big difference between passing the object and passing a reference. If the signature is MyLargeObject b then you are passing a full copy on the stack. Not good. If it is MyLargeObject & b then you are only passing a single pointer. Good. But... if the object is going to change (or worse yet, get deleted) while running the background task then you must make a copy. It is better is to favor an immutable object style. Can make MyLargeObject read only? Or guarantee it will not change? This feels like a problem that is solved by re-thinking the overall dataflow and context. Commented Dec 2, 2024 at 15:38
  • I know that the what the static analyzer says is just a suggestion, but I may need to explain why I am ignoring it so I am looking for confirmation for my assumption. Commented Dec 2, 2024 at 15:39

1 Answer 1

3

Task functor accepting an object by reference seems like a reasonable suggestion. Note that it does not imply that task's shared state should store reference to the object from library callback. Task should create a copy so it survives long enough, however functor should accept a reference to avoid yet another copy when it is invoked.

#include <future>
#include <iostream>

struct Object
{
    Object()
    { ::std::cout << static_cast<void *>(this) << " Object{}\n"; }
    Object(Object const & object)
    { ::std::cout << static_cast<void *>(this) << " Object{copy}" << static_cast<void const *>(&object) <<"\n"; }
    ~Object()
    { ::std::cout << static_cast<void *>(this) << " ~Object\n"; }
};

void ByRef(Object const & object)
{ ::std::cout << static_cast<void const *>(&object) << " ByRef\n"; }
void ByCopy(Object const object)
{ ::std::cout << static_cast<void const *>(&object) << " ByCopy\n"; }
void Callback(Object const & object)
{
    ::std::cout << "ByRef Start\n";
    ::std::async(::std::launch::async, ByRef, object).get();
    ::std::cout << "ByCopy Start\n";
    ::std::async(::std::launch::async, ByCopy, object).get();
}

int main()
{
    Object object{};
    Callback(object);
    ::std::cout << "Done\n";
    return 0;
}

online compiler

0x7ffe6a71789f Object{}
ByRef Start
0x14e6308 Object{copy}0x7ffe6a71789f
0x14e6308 ByRef
0x14e6308 ~Object
ByCopy Start
0x14e6308 Object{copy}0x7ffe6a71789f
0x7149b1bfecc8 Object{copy}0x14e6308
0x7149b1bfecc8 ByCopy
0x7149b1bfecc8 ~Object
0x14e6308 ~Object
Done
0x7ffe6a71789f ~Object

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.