[libcamera-devel] [PATCH 03/10] libcamera: Introduce Fence class

Jacopo Mondi jacopo at jmondi.org
Tue Nov 9 18:24:42 CET 2021


Hi Kieran

On Tue, Nov 09, 2021 at 01:39:58PM +0000, Kieran Bingham wrote:
> Quoting Kieran Bingham (2021-11-09 13:00:43)
> > Quoting Jacopo Mondi (2021-10-28 12:15:13)

[snip]

> > > +void Fence::moveFence(Fence &other)
> >
> > I see now that the text above really did mean moving a fence invalidates
> > it, but I'm not sure how that use case comes about.
> >
> > Could this funtion perhaps document /why/ moving a fence necessitates
> > invalidating it, and why it moves the internal fd to preserve it's
> > lifetime - but - that the fence can no longer be used... (or something
> > like that if I've inferred correctly).
> >
> >
> > > +{
> > > +       fd_ = std::move(other.fd_);
> > > +
> >
> > There might be code connected to the complete signal of the 'other'
> > fence. Should they be moved over to this? or should we explictly state
> > that listeners to that completion event are 'disconnected' (somewhat
> > implicitly).
> >
> > Perhaps we should explictily either disconnect or move them in the
> > code...?
> >
> > > +       other.disable();
> > > +       if (other.timer_.isRunning())
> > > +               other.timer_.stop();
>
> also - in this case here, the other timer is still running, so there is
> perhaps expected to be someone listing waiting for either a completed
> fence notification or a timeout. Does calling .stop() - activate the
> signal to signal a timeout? If not - perhaps we should explicitly /
> manually do so, and generate a timeout on it?
>

afaict Timer::stop() does not generate a timeout and I'm not sure
generating an event on the moved Fence is the right thing to do. How
is it the slot supposed to know if a real timeout has occurred ?

> >
> > Should you move the timeout_ value over to this one too?
> >
> > > +       other.timeout_ = 0;
> > > +}
> > > +
> > > +/**
> > > + * \brief Move-construct a Fence
> > > + * \param[in] other The other fence to move
> >
> > Ok things are becoming clearer. Perhaps:
> >
> >  *
> >  * The other fence is disabled, and invalidated while the underlying
> >  * FileDescriptor is moved to this Fence. The newly moved fence can be
> >  * re-used when required.
> >
> > > + */
> > > +Fence::Fence(Fence &&other)
> > > +       : notifier_(other.fd(), EventNotifier::Read, nullptr, false)
> > > +{
> > > +       moveFence(other);
> > > +
> > > +       notifier_.activated.connect(this, &Fence::activated);
> > > +       timer_.timeout.connect(this, &Fence::timedout);
> > > +}
> > > +
> > > +/**
> > > + * \brief Move-assign the value of the \a other fence to this
> > > + * \param[in] other The other fence to move
> > > + * \return This fence
> >
> > Something similar to the above addition maybe...
> >
> >
> > > + */
> > > +Fence &Fence::operator=(Fence &&other)
> > > +{
> > > +       moveFence(other);
> > > +
> > > +       notifier_ = EventNotifier(fd_.fd(), EventNotifier::Read, nullptr, false);
> > > +
> > > +       return *this;
> > > +}
> > > +
> > > +/**
> > > + * \fn Fence::fd() const
> > > + * \brief Return the synchronization fence file descriptor
> > > + * \return The synchronization fence file descriptor
> > > + */
> > > +
> > > +/**
> > > + * \fn Fence::timeout()
> > > + * \brief Retrieve the fence timeout
> > > + * \return The fence timeout in milliseconds
> > > + */
> > > +
> > > +/**
> > > + * \fn Fence::completed()
> > > + * \brief Check if the fence has completed before timing out
> > > + * \return True if the fence has completed
> > > + */
> > > +
> > > +/**
> > > + * \fn Fence::expired()
> > > + * \brief Check if the fence has expired before completing
> > > + * \return True if the fence has expired
> > > + */
> > > +
> > > +/**
> > > + * \brief Enable a fence by enabling events notifications
> > > + */
> > > +void Fence::enable()
> > > +{
> > > +       MutexLocker lock(mutex_);
> > > +
> > > +       expired_ = false;
> > > +       completed_ = false;
> > > +
> > > +       notifier_.setEnabled(true);
> > > +       if (timeout_)
> > > +               timer_.start(timeout_);
> > > +}
> > > +
> > > +/**
> > > + * \brief Disable a fence by disabling events notifications
> > > + */
> > > +void Fence::disable()
> > > +{
> > > +       notifier_.setEnabled(false);
> > > +}
> > > +
> > > +/**
> > > + * \var Fence::complete
> > > + * \brief The fence completion signal
> > > + *
> > > + * A Fence is completed if signalled or timeout.
> >
> > A Fence is completed when signalled or if a timeout occurs.
> >
> > > + */
> > > +
> > > +void Fence::activated()
> > > +{
> > > +       MutexLocker lock(mutex_);
> > > +
> > > +       if (timer_.isRunning())
> > > +               timer_.stop();
> > > +
> > > +       completed_ = true;
> > > +       expired_ = false;
> > > +
> > > +       complete.emit();
> >
> > Passing the expiration state as a boolean here might help the receiver
> > know why it completed.
> >
> > But maybe that's optional - or better handled as you have it anyway.
> >
> > > +}
> > > +
> > > +void Fence::timedout()
> > > +{
> > > +       MutexLocker lock(mutex_);
> > > +
> > > +       expired_ = true;
> > > +       completed_ = false;
> > > +
> > > +       /* Disable events notification after timeout. */
> > > +       disable();
> > > +
> > > +       complete.emit();
> > > +}
> > > +
> > > +} /* namespace libcamera */
> > > diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> > > index 6727a777d804..6fb0d5f49b63 100644
> > > --- a/src/libcamera/meson.build
> > > +++ b/src/libcamera/meson.build
> > > @@ -14,6 +14,7 @@ libcamera_sources = files([
> > >      'delayed_controls.cpp',
> > >      'device_enumerator.cpp',
> > >      'device_enumerator_sysfs.cpp',
> > > +    'fence.cpp',
> > >      'file_descriptor.cpp',
> > >      'formats.cpp',
> > >      'framebuffer.cpp',
> > > --
> > > 2.33.1
> > >


More information about the libcamera-devel mailing list