Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ base ] Add non-blocking and timeout variants for channelGet #3435

Open
wants to merge 53 commits into
base: main
Choose a base branch
from

Conversation

Matthew-Mosior
Copy link
Contributor

@Matthew-Mosior Matthew-Mosior commented Dec 4, 2024

Description

This PR adds a two new functions in System.Concurrency, channelGetNonBlocking and channelGetWithTimeout (only for the chez backend).

Credit to @emdash and @cypheon for review and feedback.

This PR closes #3424.

Should this change go in the CHANGELOG?

  • If this is a fix, user-facing change, a compiler change, or a new paper
    implementation, I have updated CHANGELOG_NEXT.md (and potentially also
    CONTRIBUTORS.md).

…g with return values of blodwen-channel-get-non-blocking.
@Matthew-Mosior Matthew-Mosior changed the title [ lib] Add Non-Blocking and Timeout variants for channelGet [ lib ] Add Non-Blocking and Timeout variants for channelGet Dec 4, 2024
@Matthew-Mosior Matthew-Mosior changed the title [ lib ] Add Non-Blocking and Timeout variants for channelGet [ libs ] Add Non-Blocking and Timeout variants for channelGet Dec 4, 2024
@Matthew-Mosior Matthew-Mosior changed the title [ libs ] Add Non-Blocking and Timeout variants for channelGet [ base ] Add Non-Blocking and Timeout variants for channelGet Dec 4, 2024
@Matthew-Mosior Matthew-Mosior changed the title [ base ] Add Non-Blocking and Timeout variants for channelGet [ base ] Add non-blocking and timeout variants for channelGet Dec 4, 2024
Copy link

@emdash emdash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really a member of this project, so I can't approve it, but I'll at least provide some initial feedback.

Hopefully this will get some other folks to chime in.

libs/base/System/Concurrency.idr Outdated Show resolved Hide resolved
libs/base/System/Concurrency.idr Outdated Show resolved Hide resolved
libs/base/System/Concurrency.idr Outdated Show resolved Hide resolved
support/chez/support.ss Show resolved Hide resolved
tests/allschemes/channels007/Main.idr Outdated Show resolved Hide resolved
tests/allschemes/channels008/Main.idr Outdated Show resolved Hide resolved
tests/allschemes/channels008/Main.idr Outdated Show resolved Hide resolved
@Matthew-Mosior
Copy link
Contributor Author

I'm not really a member of this project, so I can't approve it, but I'll at least provide some initial feedback.

Hopefully this will get some other folks to chime in.

Thank you for taking your time to look this over and provide feedback.

@emdash
Copy link

emdash commented Dec 6, 2024

I'm pretty satisfied with the general shape of this now. I will yield the conversation to more seasoned Idris devs.

@cypheon
Copy link
Contributor

cypheon commented Dec 7, 2024

If I understand correctly, you introduced the generic object to/from Scheme conversion because, essentially you need to return a Maybe a from a %foreign scheme: function, but I think there are to better alternatives to that:

  1. In the Scheme support code, directly return '() (which is the runtime encoding of Nothing or (box $RESULT) which corresponds to Just $RESULT.
    Advantage: less code, Disadvantage: couples the code to the runtime representation of Maybe a
  2. Return a Scheme record like (define-record channel-result (present val)), (present is a boolean indicating if the result contains a value) along that, define two extra %foreign functions: prim_channelObjectIsPresent : ChannelObject -> Int and prim_channelObjectGet : ChannelObject -> a. This pattern is for example already used in the codebase here: libs/base/System/Clock.idr:237-241
    Advantage: more robust with regards to future changes in the runtime representation, Disadvantage: slightly more code

Both approaches share the advantage, that they don't couple the two functions directly to the Chez runtime and other backends can implement them by providing implementations for the 2 (or 4)%foreign functions related to non-blocking channel access.

Furthermore, it should be possible to implement blodwen-channel-get-with-timeout without a busy-waiting loop that repeatedly calls sleep:
Chez's condition-wait function takes an (optional) third argument to pass a timeout limit. This is already used here: support/chez/support.ss:460. Using that I think you can get rid of the sleep calls in the loop.

@Matthew-Mosior
Copy link
Contributor Author

Matthew-Mosior commented Dec 7, 2024

If I understand correctly, you introduced the generic object to/from Scheme conversion because, essentially you need to return a Maybe a from a %foreign scheme: function, but I think there are to better alternatives to that:

1. In the Scheme support code, directly return `'()` (which is the runtime encoding of `Nothing` or `(box  $RESULT)` which corresponds to `Just $RESULT`.
   Advantage: less code, Disadvantage: couples the code to the runtime representation of `Maybe a`

2. Return a Scheme record like `(define-record channel-result (present val))`, (`present` is a boolean indicating if the result contains a value) along that, define two extra `%foreign` functions: `prim_channelObjectIsPresent : ChannelObject -> Int` and `prim_channelObjectGet : ChannelObject -> a`. This pattern is for example already used in the codebase here: [libs/base/System/Clock.idr:237-241](https://github.com/idris-lang/Idris2/blob/ec74792a49bf4d22509172d1f03d153ffca1b95c/libs/base/System/Clock.idr#L237C1-L241C24)
   Advantage: more robust with regards to future changes in the runtime representation, Disadvantage: slightly more code

Both approaches share the advantage, that they don't couple the two functions directly to the Chez runtime and other backends can implement them by providing implementations for the 2 (or 4)%foreign functions related to non-blocking channel access.

Furthermore, it should be possible to implement blodwen-channel-get-with-timeout without a busy-waiting loop that repeatedly calls sleep: Chez's condition-wait function takes an (optional) third argument to pass a timeout limit. This is already used here: support/chez/support.ss:460. Using that I think you can get rid of the sleep calls in the loop.

Thank you for your feedback! I will work on implementing alternative 1.

Ah I see, I'll work on re-working blodwen-channel-get-with-timeout to use that additional timeout argument instead of using a sleep loop.

@Matthew-Mosior
Copy link
Contributor Author

@cypheon

I've addressed your feedback via 6b13dc8 / fa50df7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

System.Concurrency.channelGet is hard to use and too coupled into scheme support code
4 participants