yaq-project / yaq-python

Repository for yaq core python packages.
https://yaq.fyi
GNU Lesser General Public License v3.0
5 stars 5 forks source link

Separate loop for measure? #32

Closed kameyer226 closed 1 year ago

kameyer226 commented 1 year ago

_has_measure_trigger.py: 33

def measure(self, loop: bool = False) -> int:
    """Start a measurement, optionally looping.

    Sensor will remain busy until measurement completes.

    Parameters
    ----------
    loop: bool, optional
        Toggle looping behavior. Default False.

    See Also
    --------
    stop_looping
    """
    self._looping = loop
    if not self._busy:
        self._busy = True
        self._tasks.append(self._loop.create_task(self._runner()))
    return self._measurement_id + 1

async def _runner(self) -> None:
    """Handle execution of _measure, including looping and setting of _measurement_id."""
    while True:
        self._measured = await self._measure()
        assert set(self._measured.keys()) == set(self._channel_names)
        self._measurement_id += 1
        self._measured["measurement_id"] = self._measurement_id
        if "has-mapping" in self._traits:
            self._measured["mapping_id"] = self._mapping_id  # type: ignore
        if not self._looping:
            self._busy = False
            break
        await asyncio.sleep(0)
    current_task = asyncio.current_task()
    if current_task:
        self._tasks.remove(current_task)

Doesn't this mean that the runner has to be in a separate loop from the main daemon loop? Otherwise it could be seeing and trying to remove update_state and/or save_state when it shouldn't be.

untzag commented 1 year ago

@kameyer226 It seems like you are trying to grok how the event loop works in asyncio. Async programming is a popular and robust way to achieve concurrency without risking collisions like you would with traditional multithread or multiprocess approaches. The really powerful feature of the async programming style is that we control exactly which blocks of code run synchronously and when we allow other tasks to run. The await syntax tells asyncio that we are willing to run other tasks if they are available. Consider referring to asyncio documentation and working through examples to understand these concepts---concurrency is complex so you might need to set aside some time.

Is there a particular measurement-related problem you are facing?

seeing and trying to remove update_state and/or save_state when it shouldn't be

This might indicate that you've had a problem. Could you say more? Are you experiencing a specific problem within a specific daemon?

Any context would be appreciated.

kameyer226 commented 1 year ago

Yes, it is a popular way to run concurrent operations. I completed programming one of these. It can be quite complex!

untzag commented 1 year ago

Great, glad to hear it.