smart pointers

I am writing a program with two parts. (A) sends an object to (B) which stores it, and once sent, (A) can only modify part of that object. I am stuck with pointers since I need low latency. Initially I had been using shared_ptr, but obviously (A) can modify the content in that ptr after (B) gets it, and I don't want (B) to make a copy of that object since it caused extra latency. I'm not familiar with all those smart pointers, but initially I'm thinking unique_ptr may do the trick. I'm wondering if this will work:

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
struct SubObject {
  long change_me;
}

struct Object {
  long var_cannot_be_changed;
  
  shared_ptr<SubObject> var_can_be_changed;
}
// within (A)
shared_ptr<SubObject> changeable_obj;
unique_ptr<Object> unchanged_obj;
void A::sendToB() {
  unchanged_obj->var_can_be_changed = changeable_obj;
  B::getObj(unchanged_obj);
}
void A::changeSomething() {
  changeable_obj->change_me++;
}

// within (B)
unique_ptr<Object> stored_obj;
void BB::getObj(const unique_ptr<Object>& ptr) {
  stored_obj = ptr;
}
Can you give more details about what you're trying to do? This design seems rather unusual to me, and it seems like it'd be easy to screw something up.

What you have there will basically work, if I understood you correctly, although you need to fix a few things about how you move the std::unique_ptr around:
1
2
3
4
5
B::getObj(std::move(unchanged_obj));

void B::getObj(unique_ptr<Object> &&ptr) {
  stored_obj = std::move(ptr);
}
std::unique_ptr can't be copied, so if you pass it by const reference you won't be able to do anything to the pointer itself, only to the object.
Last edited on
is A going to mess with it before it sends it to B? If not, can you solve this with just a const in the right place? (in this case, it may be references not pointers?)

also, is there an inverse solution where B gets it first and A picks it up *from* B? As in A.get returns B.get()?
Last edited on
Here is the flow:

Step 1: (A) creates a smart pointer of "Object" with some contents
Step 2: (A) sends the pointer to (B), who stores the pointer without copying the content.
Step 3: After a while, (A) modifies the changeable part of the "Object", and expect (B) to automatically pick up the change without sending it to (B) again.


Normally, using shared_ptr does the trick. However, there are parts of the "Object" that is unchangeable after sending to (B) in step 2. With shared_ptr, (A) can modify any field in "Object" of its own, and the change is automatically reflected in (B). Therefore, I am thinking of using unique_ptr for "Object" and shared_ptr for the changeable part of the "Object". However, I don't exactly know how to get it work in code.
Something along these lines, perhaps:

Using unique pointer:
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
#include <iostream>
#include <memory>

struct object
{
    explicit object( int changeable = 0, int unchangeable = 0 )
        : changeable(changeable), unchangeable(unchangeable) {}

    int changeable ;
    const int unchangeable ;
};

struct B
{
    // (B) stores the pointer without copying the content.
    void accept( const object* p ) { ptr = p ; }

    // expect (B) to automatically pick up the change
    void show_state_of_stored_object() const
    {
        if(ptr)
        {
            std::cout << "changeable == " << ptr->changeable
                      << ", unchangeable == " << ptr->unchangeable << '\n' ;

            // ptr->changeable = 0 ; // *** error: (B) is not allowed to modify the object
        }

        else std::cout << "there is no object\n" ;
    }

    const object* ptr = nullptr ; // pointer to const object
};

struct A
{
    // Step 1: (A) creates a smart pointer of "Object" with some contents
    explicit A( int v ) : ptr( std::make_unique<object>( v, v+12 ) ) {}

    // Step 2: (A) sends the (raw) pointer to (B)
    void send_to( B& b ) { b.accept( ptr.get() ) ; }

    // Step 3: (A) modifies the changeable part of the "Object"
    void modify_object() { ptr->changeable += 777 ; }

    std::unique_ptr<object> ptr ;
};

int main()
{
    A a(25) ;
    B b ;

    a.send_to(b) ; // send the (raw) pointer to B
    b.show_state_of_stored_object() ; // changeable == 25, unchangeable == 37

    // (A) modifies the changeable part of the "Object"
    a.modify_object() ;
    // expect (B) to automatically pick up the change
    b.show_state_of_stored_object() ; // changeable == 802, unchangeable == 37

    a.ptr = nullptr ; // kill the object
    b.accept(nullptr) ; // notify (B) that the object is no longer there
    b.show_state_of_stored_object() ; // there is no object
}

http://coliru.stacked-crooked.com/a/3c1e785fe576a6f2


Using shared pointer:
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
#include <iostream>
#include <memory>

struct object
{
    explicit object( int changeable = 0, int unchangeable = 0 )
        : changeable(changeable), unchangeable(unchangeable) {}

    int changeable ;
    const int unchangeable ;
};

struct B
{
    // (B) stores the pointer without copying the content.
    void accept( const std::shared_ptr< const object >& p ) { weak_ptr = p ; }

    // expect (B) to automatically pick up the change
    void show_state_of_stored_object() const
    {
        // try to get a temporary shared pointer to the object
        auto ptr = weak_ptr.lock() ; // note: shared_ptr to const object

        if(ptr) // if the object still exists
        {
            std::cout << "changeable == " << ptr->changeable
                      << ", unchangeable == " << ptr->unchangeable << '\n' ;

            // ptr->changeable = 0 ; // *** error: (B) is not allowed to modify the object

        }

        else std::cout << "the object has expired\n" ;
    }

    std::weak_ptr<const object> weak_ptr ; // smart pointer to const object
};

struct A
{
    // Step 1: (A) creates a smart pointer of "Object" with some contents
    explicit A( int v ) : ptr( std::make_shared<object>( v, v+12 ) ) {}

    // Step 2: (A) sends the pointer to (B)
    void send_to( B& b ) { b.accept(ptr) ; }

    // Step 3: (A) modifies the changeable part of the "Object"
    void modify_object() { ptr->changeable += 777 ; }

    std::shared_ptr<object> ptr ;
};

int main()
{
    A a(25) ;
    B b ;

    a.send_to(b) ; // send the pointer to B
    b.show_state_of_stored_object() ; // changeable == 25, unchangeable == 37

    // (A) modifies the changeable part of the "Object"
    a.modify_object() ;
    // expect (B) to automatically pick up the change
    b.show_state_of_stored_object() ; // changeable == 802, unchangeable == 37

    a.ptr = nullptr ; // kill the object
    b.show_state_of_stored_object() ; // the object has expired
}

http://coliru.stacked-crooked.com/a/85074ba8866e601c
Last edited on
Thanks, I'll try it out
Topic archived. No new replies allowed.