Re: [libgpiod] cxx bindings: time_point vs duration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Oct 15, 2020 at 12:57 PM Helmut Grohne <helmut.grohne@xxxxxxxxxx> wrote:
>
> Hi,
>
> On Thu, Oct 15, 2020 at 12:05:23PM +0200, Bartosz Golaszewski wrote:
> > In case of the event timestamps - we get them from the kernel as
> > 64-bit unsigned integers. They're then converted to struct timespec as
> > defined by libc and eventually to ::std::chrono:duration. The
> > timestamps use the MONOTONIC kernel clock - the same that you would
> > use by calling clock_gettime(CLOCK_MONOTONIC, ...). Is there any way
> > to couple the C++ time_point to this clock?
>
> I got that wrong then as I thought they were wall clock time.

Well, it's a long story. It used to be what the kernel calls REALTIME
clock, then it was changed to MONOTONIC and now there's a suggestion
to make it configurable in v2. More on that here[1].

> CLOCK_MONOTONIC is the thing that backs std::chrono::steady_clock on
> Linux. At least gcc and clang's libcxx implement steady_clock using
> nanosecond resolution. I don't thing nanosecond resolution is
> guarantueed, but maybe this is good enough and you can just use
> steady_clock? That would certainly be most welcome by consuming client
> code.
>

One question is: even if on linux the steady_clock is backed by
CLOCK_MONOTONIC, is this a guarantee or just implementation? And can
we rely on this if it's not defined?

> > Me neither, but the new user API exposed by the kernel addresses a lot
> > of issues and adds new features and it's really impossible to keep the
> > current library API while also leveraging them. I'll keep supporting
> > the v1.6 stable branch for a long time though.
>
> Great news. Thank you.
>
> > Yes, it's what I intended indeed. I'm however worried that this isn't
> > the best approach. Having learned more, I now think that lines should
> > somehow weakly reference the chip - to emphasize that they don't
> > control its lifetime in any way (which is the case now with each line
> > storing a hard reference to the chip). Also what happens currently is
> > the fact that a new line object is created each time get_line() method
> > is called because we can't store lines in some array within the chip
> > because that would lead to circular references. Maybe a line should
> > store a weak_ptr to the underlying ::gpiod_chip? But then it would
> > create a new chip object every time get_chip() is called. Is there any
> > way around it? Making the chip and line non-copyable and expediting
> > any shared_ptr management to the user?
>
> First of all, I don't think any of these types need to be copyable.
> Keeping them moveable should be simple and makes handling them easy
> enough.
>

Right now we rely on them being copyable to store them in
::gpiod::line_bulk objects so that needs addressing too.

> It seems like you'd want a chip to include all lines as is the case for
> the C-api already. In that case, a line does not exist by itself, it
> only is an observable part of a chip. I'm not convinced that a line
> should weakly reference a chip. If you have a line and the underlying
> chip disappears, all the gpiod_lines get cleared and your line suddenly
> has a dangling reference. Actually, you line would be gone if it was
> part of the chip. That does not seem useful to me. So the current design
> of having lines control the lifetime of the chip seems useful to me.
>

Yes, except that with a weak_ptr we'd at least get a bad_weak_ptr
exception instead of a segfault if the programmer goofs and lets the
chip disappear before using a line.

> Why do you take issue with the fact that each get_line creates a new
> line object? This line object practically is a counted reference on the
> chip together with a line identifier. It kinda is a complex pointer. Why
> not have two distinct pointers point to the same thing?
>

It started with Python bindings actually. The pattern over there is
similar except that Python objects are much more complex to create and
initialize. Then I realized that C++ does the same. It also seems to
me like reversed logic where a line has the power to keep the chip
alive. Just doesn't feel good and I haven't seen this pattern
anywhere.

> Likewise creating new chip objects is not a problem in my book, because
> a chip object is a (counted) reference to a gpiod_chip. Having two
> pointers should be ok. Creating them is cheap.
>

Fair enough.

> > The thing with gpiod_line struct (the one from C libgpiod, not C++
> > class) is that the owner is the chip (struct gpiod_chip) - there's no
> > need to free any resources, they'll be freed when the chip goes out of
> > scope. You can copy the line pointer all you want, there's always a
> > single line behind stored in the opaque struct gpiod_chip. So in C++ -
> > I suppose - the chip should really own the C++ line (stored in a
> > vector maybe) and the line should at most weakly reference the chip
> > object. I'm just not sure how to correctly approach this so any advice
> > is welcome.
>
> That helps a lot with my understanding. I mostly concur up to the point
> where you say that a chip should own the C++ line. The C++ line
> currently is a counted reference on a gpiod_chip together with a line
> identifier. I don't see what's so precious about this to ensure it is
> not copied. That seems entirely fine with me.
>
> Now if you go the route and have chips own lines, then your back
> reference from line to chip can be a plain pointer. The forward
> reference ensures that the pointer is always valid. It's still circular,
> but you don't have to mess with weak_ptrs as long as destruction is
> careful.
>
> So this seems mostly fine as is. Having lines manage the lifetime of
> chips is very convenient for using the library.
>
> Helmut

That's interesting to read. I was under the impression that this is
bad C++ (or OOP in general). I have to think about it some more
though, because my gut is telling me this is just wrong on the logical
level - even if it's convenient.

Bartosz

[1] https://www.spinics.net/lists/linux-gpio/msg53796.html



[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux