Skip to content

Split close(cause...) into two interfaces #325

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

Closed
venkatperi opened this issue Apr 11, 2018 · 6 comments
Closed

Split close(cause...) into two interfaces #325

venkatperi opened this issue Apr 11, 2018 · 6 comments

Comments

@venkatperi
Copy link
Contributor

venkatperi commented Apr 11, 2018

Job, ReceiveChannel and possibly other interfaces have a common function close(cause: Throwable? = null). I see one issue and a couple of thoughts about this:

Issue

Consider an interface which inherits from Job and ReceiveChannel:

interface JobWithChannel<E> : Job, ReceiveChannel<E>

The compiler is upset because both interfaces have close w/default values.

More than one overridden descriptor declares a default value for 
'value-parameter cause: Throwable? = ... defined in '...'. As the compiler 
can not make sure these values agree, this is not allowed.

Recommendations

Consider inheriting from java.io.Closeable (e.g. for auto close with use) and a new interface say CloseableWithCause. This will probably be a breaking change (close() returns Boolean currently)

The compiler is OK with the code below:

interface CloseableWithCause {
  fun close(cause: Throwable)
}

interface P : Closeable, CloseableWithCause
interface Q : Closeable, CloseableWithCause

interface X : P, Q {
  fun test() {
    close()
    close(Exception())
  }
}
@elizarov
Copy link
Contributor

We had an interface that extends both Job and ReceiveChannel and decided to avoid it. The current thinking is to provide Channel.job property instead in the future. See #260

There does not see to be a need for another asynchronously closeable abstraction. It looks like Job is good enough. See also this discussion: #240 (comment)

@IonoclastBrigham
Copy link

@elizarov I'd like to advocate for this on more general utility/consistency terms.

Channel (and others) have a close() method you can (need to!) call, possibly with no arguments. This is a Closeable in all but name. I'm currently cranking out use functions and extension methods for these things, which is just another potential source of bugs.

There's also a consistency argument; ThreadPoolDispatcher implements Closeable, and thus I can rely on the standard .use() extension. Seems really weird that within a single library somethings you close are Closeable, and some things you close aren't.

@elizarov
Copy link
Contributor

@IonoclastBrigham I'm on the fence on this issue. On one side your argument is perfectly valid. Channels are closeable. On the other side, I don't want to promote the whole use { ... } pattern, since it is very error-prone. I'd be very glad if you can share some bits of your use-using code to see if it can be replaced with something better.

@IonoclastBrigham
Copy link

It looks something like...

readerChannel(bufferedreader).use { chan ->
  while (running) {
    select<Unit> {
      chan.onReceiveOrNull { line ->
        // ...
      }

      // ...
    }
  }
}

where readerChannel() basically just launches a tight loop that calls .readLine() on the BufferedReader and sends the result on the Channel. (The reader is owned and cleaned up elsewhere.)

@elizarov
Copy link
Contributor

elizarov commented Jul 8, 2018

@IonoclastBrigham We have consume extension for this purpose: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume.html

However, it is not as convenient for your use-case as use, because it makes the channel available as receiver.

I cannot really explain it, but somehow I don't think we need any kind of "closeable" for channels, but we can define use extension on ReceiveChannel: #429

@qwwdfsad
Copy link
Collaborator

Closing this one as obsolete.
We have use-like extensions on channels (and probably we will rename it in the face of cold streams) and we do not want to encourage people to mix Closeable and SendChannel in the one entity, at least for now

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

No branches or pull requests

4 participants