linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kent Gibson <warthog618@gmail.com>
To: Bartosz Golaszewski <brgl@bgdev.pl>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	Jack Winch <sunt.un.morcov@gmail.com>,
	Helmut Grohne <helmut.grohne@intenta.de>,
	linux-gpio@vger.kernel.org,
	Bartosz Golaszewski <bgolaszewski@baylibre.com>
Subject: Re: [PATCH v2] treewide: rework struct gpiod_line_bulk
Date: Wed, 28 Oct 2020 17:39:28 +0800	[thread overview]
Message-ID: <20201028093928.GA152368@sol> (raw)
In-Reply-To: <20201027091715.8958-1-brgl@bgdev.pl>

On Tue, Oct 27, 2020 at 10:17:15AM +0100, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> 

Subject should be prefixed with [libgpiod] according to the README ;).

[snip]

> diff --git a/bindings/cxx/line_bulk.cpp b/bindings/cxx/line_bulk.cpp
> index e77baa2..e7bd20e 100644
> --- a/bindings/cxx/line_bulk.cpp
> +++ b/bindings/cxx/line_bulk.cpp
> @@ -46,6 +46,29 @@ const ::std::map<::std::bitset<32>, int, bitset_cmp> reqflag_mapping = {
>  	{ line_request::FLAG_BIAS_PULL_UP,	GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP, },
>  };
> 

A - see comment after line_bulk::event_wait()

> +struct line_bulk_iter_deleter
> +{
> +	void operator()(::gpiod_line_bulk_iter *iter)
> +	{
> +		::gpiod_line_bulk_iter_free(iter);
> +	}
> +};
> +
> +using line_bulk_iter_ptr = ::std::unique_ptr<::gpiod_line_bulk_iter,
> +					     line_bulk_iter_deleter>;
> +
> +line_bulk_iter_ptr make_line_bulk_iter(::gpiod_line_bulk *bulk)
> +{
> +	::gpiod_line_bulk_iter *iter;
> +
> +	iter = ::gpiod_line_bulk_iter_new(bulk);
> +	if (!iter)
> +		throw ::std::system_error(errno, ::std::system_category(),
> +					  "Unable to create new line bulk iterator");
> +
> +	return line_bulk_iter_ptr(iter);
> +}
> +

B - see comment after line_bulk::event_wait()

>  } /* namespace */
>  

[snip]

> @@ -263,27 +270,26 @@ line_bulk line_bulk::event_wait(const ::std::chrono::nanoseconds& timeout) const
>  {
>  	this->throw_if_empty();
>  
> -	::gpiod_line_bulk bulk, event_bulk;
> +	line_bulk_ptr ev_bulk(::gpiod_line_bulk_new(this->size()));
> +	auto chip = this->_m_bulk[0].get_chip();

Move chip into the block where it is used.

> +	auto bulk = this->to_line_bulk();
>  	::timespec ts;
>  	line_bulk ret;
>  	int rv;
>  
> -	this->to_line_bulk(::std::addressof(bulk));
> -
> -	::gpiod_line_bulk_init(::std::addressof(event_bulk));
> -
>  	ts.tv_sec = timeout.count() / 1000000000ULL;
>  	ts.tv_nsec = timeout.count() % 1000000000ULL;
>  
> -	rv = ::gpiod_line_event_wait_bulk(::std::addressof(bulk),
> -					  ::std::addressof(ts),
> -					  ::std::addressof(event_bulk));
> +	rv = ::gpiod_line_event_wait_bulk(bulk.get(), ::std::addressof(ts), ev_bulk.get());
>  	if (rv < 0) {
>  		throw ::std::system_error(errno, ::std::system_category(),
>  					  "error polling for events");
>  	} else if (rv > 0) {
> -		for (unsigned int i = 0; i < event_bulk.num_lines; i++)
> -			ret.append(line(event_bulk.lines[i], this->_m_bulk[i].get_chip()));
> +		auto iter = make_line_bulk_iter(ev_bulk.get());
> +		::gpiod_line *curr_line;
> +
> +		gpiod_line_bulk_iter_foreach_line(iter.get(), curr_line)
> +			ret.append(line(curr_line, chip));
>  	}
>  

If you replace the gpiod_line_bulk_iter_foreach_line() here with
manually looping over the bulk lines then everything from A to B above
can be dropped.

i.e. 
-               auto iter = make_line_bulk_iter(ev_bulk.get());
-               ::gpiod_line *curr_line;
+               auto chip = this->_m_bulk[0].get_chip();
+               auto num_lines = ::gpiod_line_bulk_num_lines(ev_bulk.get());

-               gpiod_line_bulk_iter_foreach_line(iter.get(), curr_line)
-                       ret.append(line(curr_line, chip));
+               for (unsigned int i = 0; i < num_lines; i++)
+                       ret.append(line(::gpiod_line_bulk_get_line(ev_bulk.get(), i), chip));

That includes the chip relocation, btw.

[snip]

>  }
> @@ -1715,9 +1751,10 @@ static PyObject *gpiod_LineBulk_event_wait(gpiod_LineBulkObject *self,
>  {
>  	static char *kwlist[] = { "sec", "nsec", NULL };
>  
> -	struct gpiod_line_bulk bulk, ev_bulk;
> -	struct gpiod_line *line, **line_ptr;
> +	struct gpiod_line_bulk *bulk, *ev_bulk;
> +	struct gpiod_line_bulk_iter *iter;
>  	gpiod_LineObject *line_obj;
> +	struct gpiod_line *line;
>  	gpiod_ChipObject *owner;
>  	long sec = 0, nsec = 0;
>  	struct timespec ts;
> @@ -1736,37 +1773,64 @@ static PyObject *gpiod_LineBulk_event_wait(gpiod_LineBulkObject *self,
>  	ts.tv_sec = sec;
>  	ts.tv_nsec = nsec;
>  
> -	gpiod_LineBulkObjToCLineBulk(self, &bulk);
> +	bulk = gpiod_LineBulkObjToCLineBulk(self);
> +	if (!bulk)
> +		return NULL;
> +
> +	ev_bulk = gpiod_line_bulk_new(self->num_lines);
> +	if (!ev_bulk) {
> +		gpiod_line_bulk_free(bulk);
> +		return NULL;
> +	}
>  
>  	Py_BEGIN_ALLOW_THREADS;
> -	rv = gpiod_line_event_wait_bulk(&bulk, &ts, &ev_bulk);
> +	rv = gpiod_line_event_wait_bulk(bulk, &ts, ev_bulk);
> +	gpiod_line_bulk_free(bulk);
>  	Py_END_ALLOW_THREADS;
> -	if (rv < 0)
> +	if (rv < 0) {
> +		gpiod_line_bulk_free(ev_bulk);
>  		return PyErr_SetFromErrno(PyExc_OSError);
> -	else if (rv == 0)
> +	} else if (rv == 0) {
> +		gpiod_line_bulk_free(ev_bulk);
>  		Py_RETURN_NONE;
> +	}
>  
> -	ret = PyList_New(gpiod_line_bulk_num_lines(&ev_bulk));
> -	if (!ret)
> +	ret = PyList_New(gpiod_line_bulk_num_lines(ev_bulk));
> +	if (!ret) {
> +		gpiod_line_bulk_free(ev_bulk);
>  		return NULL;
> +	}
>  
>  	owner = ((gpiod_LineObject *)(self->lines[0]))->owner;
>  
> +	iter = gpiod_line_bulk_iter_new(ev_bulk);
> +	if (!iter) {
> +		gpiod_line_bulk_free(ev_bulk);
> +		return PyErr_SetFromErrno(PyExc_OSError);
> +	}
> +
>  	i = 0;
> -	gpiod_line_bulk_foreach_line(&ev_bulk, line, line_ptr) {
> +	gpiod_line_bulk_iter_foreach_line(iter, line) {
>  		line_obj = gpiod_MakeLineObject(owner, line);
>  		if (!line_obj) {
> +			gpiod_line_bulk_iter_free(iter);
> +			gpiod_line_bulk_free(ev_bulk);
>  			Py_DECREF(ret);
>  			return NULL;
>  		}
>  
>  		rv = PyList_SetItem(ret, i++, (PyObject *)line_obj);
>  		if (rv < 0) {
> +			gpiod_line_bulk_iter_free(iter);
> +			gpiod_line_bulk_free(ev_bulk);
>  			Py_DECREF(ret);
>  			return NULL;
>  		}
>  	}
>  

This function can be simplified by looping over the bulk manually rather
than using the line_bulk_iter.

> +	gpiod_line_bulk_iter_free(iter);
> +	gpiod_line_bulk_free(ev_bulk);
> +
>  	return ret;
>  }
>  
> @@ -2241,41 +2305,59 @@ PyDoc_STRVAR(gpiod_Chip_get_all_lines_doc,
>  static gpiod_LineBulkObject *
>  gpiod_Chip_get_all_lines(gpiod_ChipObject *self, PyObject *Py_UNUSED(ignored))
>  {
> +	struct gpiod_line_bulk_iter *iter;
>  	gpiod_LineBulkObject *bulk_obj;
> -	struct gpiod_line_bulk bulk;
> +	struct gpiod_line_bulk *bulk;
>  	gpiod_LineObject *line_obj;
>  	struct gpiod_line *line;
> -	unsigned int offset;
> +	unsigned int index = 0;
>  	PyObject *list;
>  	int rv;
>  
>  	if (gpiod_ChipIsClosed(self))
>  		return NULL;
>  
> -	rv = gpiod_chip_get_all_lines(self->chip, &bulk);
> -	if (rv)
> +	bulk = gpiod_chip_get_all_lines(self->chip);
> +	if (!bulk)
>  		return (gpiod_LineBulkObject *)PyErr_SetFromErrno(
>  							PyExc_OSError);
>  
> -	list = PyList_New(gpiod_line_bulk_num_lines(&bulk));
> -	if (!list)
> +	list = PyList_New(gpiod_line_bulk_num_lines(bulk));
> +	if (!list) {
> +		gpiod_line_bulk_free(bulk);
>  		return NULL;
> +	}
>  
> -	gpiod_line_bulk_foreach_line_off(&bulk, line, offset) {
> +	iter = gpiod_line_bulk_iter_new(bulk);
> +	if (!iter) {
> +		gpiod_line_bulk_free(bulk);
> +		Py_DECREF(list);
> +		return (gpiod_LineBulkObject *)PyErr_SetFromErrno(
> +							PyExc_OSError);
> +	}
> +
> +	gpiod_line_bulk_iter_foreach_line(iter, line) {
>  		line_obj = gpiod_MakeLineObject(self, line);
>  		if (!line_obj) {
> +			gpiod_line_bulk_iter_free(iter);
> +			gpiod_line_bulk_free(bulk);
>  			Py_DECREF(list);
>  			return NULL;
>  		}
>

Again, NOT using the line_bulk_iter here, and manually looping instead, is
actually simpler and cleaner.

Cheers,
Kent.


  reply	other threads:[~2020-10-28 21:58 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-27  9:17 [PATCH v2] treewide: rework struct gpiod_line_bulk Bartosz Golaszewski
2020-10-28  9:39 ` Kent Gibson [this message]
2020-10-28 13:19   ` Bartosz Golaszewski
2020-10-28 15:03     ` Kent Gibson
2020-10-28 16:26       ` Bartosz Golaszewski
2020-10-28 23:07         ` Kent Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201028093928.GA152368@sol \
    --to=warthog618@gmail.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=bgolaszewski@baylibre.com \
    --cc=brgl@bgdev.pl \
    --cc=geert@linux-m68k.org \
    --cc=helmut.grohne@intenta.de \
    --cc=linux-gpio@vger.kernel.org \
    --cc=sunt.un.morcov@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).