Re: [PATCH v2] treewide: rework struct gpiod_line_bulk

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

 



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

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.




[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