Skip to content

Add * operator to SingletonPtr #8001

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 8, 2018
Merged

Conversation

kjbracey
Copy link
Contributor

@kjbracey kjbracey commented Sep 5, 2018

Description

Sometimes you want don't want to directly call a method on your SingletonPtr-wrapped object, but you want to pass it to something else.

For example

SingletonPtr<PlatformMutex> mutex;
mutex->lock();

is fine, but what about

SingletonPtr<PlatformMutex> mutex;
ScopedLock<PlatformMutex> lock(*mutex.get());

Add an overload for operator* to make this more elegant:

SingletonPtr<PlatformMutex> mutex;
ScopedLock<PlatformMutex> lock(*mutex);

This addition is consistent with standard C++ classes such as unique_ptr and shared_ptr, which likewise have get, operator-> and operator*.

Pull request type

[ ] Fix
[ ] Refactor
[ ] Target update
[X] Functionality change
[ ] Breaking change

Change originally proposed and discussed as part of #7924, now separated out.

Sometimes you want don't want to directly call a method on your
SingletonPtr-wrapped object, but you want to pass it to something
else.

For example

    SingletonPtr<PlatformMutex> mutex;
    mutex->lock();

is fine, but what about

    SingletonPtr<PlatformMutex> mutex;
    ScopedLock<PlatformMutex> lock(*mutex.get());

Add an overload for operator* to make this more elegant:

    SingletonPtr<PlatformMutex> mutex;
    ScopedLock<PlatformMutex> lock(*mutex);

This addition is consistent with standard C++ classes such as
`unique_ptr` and `shared_ptr`, which likewise have
get, operator-> and operator*.
Copy link
Member

@pan- pan- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally all these member function would be cons. But since none of them are I guess the proposed update is fine.

@geky
Copy link
Contributor

geky commented Sep 5, 2018

@pan-, wouldn't we have both const and non-const overloads?

@pan-
Copy link
Member

pan- commented Sep 6, 2018

@geky Not really, it is the type of the template parameter that determines the constness of the inner object. Consider the following code:

struct foo { 
    int* p;
};

void update(const foo& f) { 
    f.p[0] = 1;     // no compilation error 
    f.p= NULL;  // compilation error
}

If you look at unique_ptr, the same reasoning is applied to operator* and the member function get

@geky
Copy link
Contributor

geky commented Sep 6, 2018

Oh I see! yep you're right, we should add that at some point

@kjbracey
Copy link
Contributor Author

kjbracey commented Sep 7, 2018

I did consider making the methods const - I assume they're not because the first get() call auto-constructs the object.

We could make the methods const by adding mutables, but I can't 100% convince myself that the first get invocation is really logically const to justify that.

Can anyone point to corresponding analogues in another standard APIs?

Only thing that sprang to mind for me was "can C++14 constexpr functions have static variables"? Answer - no, but then constexpr is far more constraining.

Another thing that I've noticed is a potential alignment problem - shouldn't _data be an array of uint64_ts these days? (cf #8004, #8012)

@TeroJaasko
Copy link
Contributor

TeroJaasko commented Sep 7, 2018

@kjbracey-arm : Instead of using uint64_t to get alignment (and a few bytes of overhead for increased _data size), couldn't the compiler do that by MBED_ALIGN(8) uint8_t _data[(sizeof(T)]?

@kjbracey
Copy link
Contributor Author

kjbracey commented Sep 7, 2018

I don't believe you can use the align directives to align structure members, only top-level objects.

And even the SingletonPtr itself is not necessarily a top-level object - can be embedded in a structure.

Even if you could persuade it, I bet there's no toolchain support or optimisation for packing "X-aligned object with non-X-multiple size". All normal C objects must have size a multiple of alignment (so you can make arrays of them). Which in this case is unfortunate, as it will force 32 bits of padding cos the only other thing in the structure is that 32 bit pointer.

Hmm, having just argued that, I realise that we could maybe do something if we could find out or deduce the alignment of T. Eg if sizeof(T) % 8 != 0 we know it doesn't need 64-bit alignment. But now we need to achieve that in template magic.

@kjbracey
Copy link
Contributor Author

kjbracey commented Sep 7, 2018

Hmm, if we were using C++11, alignas(alignof(T)) would work on a member.

Not actually sure what the state of MBED_ALIGNs expansions is for members - I think it works for GCC, so probably ARM, but I don't think it does for IAR. And not sure about passing "alignof" to those, rather than just 8 or "maximum".

@pan-
Copy link
Member

pan- commented Sep 7, 2018

But now we need to achieve that in template magic.

I've done that in the past (1, 2). I'm pretty sure that's not the kind of code we want in the OS.

MBED_ALIGN should just work on GCC and ARMCC: This attribute specifies a minimum alignment for the variable or structure field, measured in bytes. However on IAR pack(alignement) should be used to operate inside structures. On this compiler MBED_ALIGN is replaced by the pragma data_alignement that only works for static and automatic variables.

I suggest we wait for language upgrade and use the maximum alignement for now as there is very few of these objects present in the codebase.


Can anyone point to corresponding analogues in another standard APIs?

The operator* or the member function get of both shared_ptr and unique_ptr are const (1, 2, 3, 4).

The caller of get don't know and don't care whether or not the initialisation happen behind the scene; that's an implementation detail.

@kjbracey
Copy link
Contributor Author

kjbracey commented Sep 7, 2018

I've done that in the past

Eeep!

Let's just uint64_t it for now...

The operator* or the member function get of both shared_ptr and unique_ptr are const

Yes, but they're naturally const, really changing nothing. Here we do have a "first called, so constructed" bit of state, and that lazy initialisation is part of the overall API.

But then, as you say, the caller of get() doesn't care about that detail. I'll make a separate PR for the const and alignment, as I think this one is fine as-is.

@TeroJaasko
Copy link
Contributor

TeroJaasko commented Sep 7, 2018

IAR 8.2, ARMC 5.06, GCC 6.3 all seem to digest __attribute__((aligned(x))) for C++ class members. Just tested with following code, and all produce correct result. I don't have IAR 7.8, so can't test on it. But as you say, the MBED_ALIGN() does not work there on IAR, as it also warns for: "[Warning] [Pe609]: this kind of pragma may not be used here"

class Test {
public:
    uint8_t dummy;
    __attribute__((aligned(8))) uint8_t array[3];
};
<..>
    printf("sizeof   Test       : %d\n", sizeof(Test);
    printf("sizeof   Test::array: %d\n", sizeof(Test::array));
    printf("offsetof Test::array: %d\n", offsetof(Test, array));

output:

sizeof   Test       : 16
sizeof   Test::array: 3
offsetof Tes2::array: 8

@NirSonnenschein
Copy link
Contributor

/morph build

@mbed-ci
Copy link

mbed-ci commented Oct 3, 2018

Build : SUCCESS

Build number : 3221
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/8001/

Triggering tests

/morph test
/morph mbed2-build

@mbed-ci
Copy link

mbed-ci commented Oct 3, 2018

@NirSonnenschein
Copy link
Contributor

/morph export-build

@mbed-ci
Copy link

mbed-ci commented Oct 3, 2018

@NirSonnenschein
Copy link
Contributor

uvision failure - retry:
/morph export-build

@mbed-ci
Copy link

mbed-ci commented Oct 4, 2018

@NirSonnenschein
Copy link
Contributor

/morph export-build

@mbed-ci
Copy link

mbed-ci commented Oct 6, 2018

@NirSonnenschein
Copy link
Contributor

/morph export-build

@mbed-ci
Copy link

mbed-ci commented Oct 7, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants