agronholm / anyio

High level asynchronous concurrency and networking framework that works on top of either trio or asyncio
MIT License
1.81k stars 138 forks source link

Expose ResourceGuard #627

Closed Fuyukai closed 1 year ago

Fuyukai commented 1 year ago

Things to check first

Feature description

ResourceGuard should be exposed publically, instead of requiring importing from an internal module.

Use case

It's a useful object for implementing streams that use pumping tasks behind the scenes.

agronholm commented 1 year ago

I've considered this. It would help if you elaborated on the use case.

gschaffner commented 1 year ago

i can't speak for others, but i implemented a ResourceGuard equivalent in a downstream library because i needed to ensure that users doing broken locking would raise instead of silently causing a framer & multiplexer to lose track of stream state and start (a) sending gibberish to the peer and/or (b) returning gibberish to the user[^1].

i also made the mistake of not exposing it publicly in that library, which led folks at work writing further-downstream code atop AnyIO+aforementioned middle lib to again reimplement a ResourceGuard equivalent a third time.

it's a tiny implementation to copy around everywhere, but i'd love to see it exposed in AnyIO.

[^1]: the library needed to use ResourceGuard, not Lock, because locking has to be done further downstream by application developers to avoid the bugs associated with using recursive locks for non-recursive tasks. for context, this is for controlling scientific instruments, where we need proper locking so that we don't have multiple clients interrupting each other's sequences of device commands/queries. these instruments are very stateful and it is annoying.

Fuyukai commented 1 year ago

It would help if you elaborated on the use case.

My client class uses a background task to read messages from the socket and turn them into objects, then publishes them on a channel for the downstream users to read. It's essentially the same reason as socket streams having their receive/sends wrapped in a conflict detector.