blob: f9865c2d16695e8baaf2b817e9cb41aaaa042282 [file] [log] [blame]
Roman Elizarov1f74a2d2018-06-29 19:19:45 +03001/*
2 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3 */
4
Sergey Mashkov86f70612017-07-25 10:59:44 +03005package kotlinx.coroutines.experimental.io.internal
6
Roman Elizarov83762032017-08-08 19:58:40 +03007import java.nio.ByteBuffer
Sergey Mashkov86f70612017-07-25 10:59:44 +03008
Roman Elizarov83762032017-08-08 19:58:40 +03009// this is MAGICAL constant that is tied to the code ByteBufferChannel (that is how much it needs extra)
10internal const val RESERVED_SIZE = 8
Sergey Mashkov86f70612017-07-25 10:59:44 +030011
Roman Elizarov83762032017-08-08 19:58:40 +030012internal val EmptyByteBuffer: ByteBuffer = ByteBuffer.allocate(0)
Roman Elizarov469cad32017-08-15 15:54:56 +030013internal val EmptyCapacity = RingBufferCapacity(0)
Roman Elizarov83762032017-08-08 19:58:40 +030014
15internal sealed class ReadWriteBufferState(
Roman Elizarov469cad32017-08-15 15:54:56 +030016 @JvmField val backingBuffer: ByteBuffer,
17 @JvmField val capacity: RingBufferCapacity
Roman Elizarov83762032017-08-08 19:58:40 +030018) {
Sergey Mashkov86f70612017-07-25 10:59:44 +030019 open val idle: Boolean get() = false
Roman Elizarov83762032017-08-08 19:58:40 +030020 open val readBuffer: ByteBuffer get() = error("read buffer is not available in state $this")
21 open val writeBuffer: ByteBuffer get() = error("write buffer is not available in state $this")
Sergey Mashkov86f70612017-07-25 10:59:44 +030022
Roman Elizarov83762032017-08-08 19:58:40 +030023 internal open fun startReading(): ReadWriteBufferState = error("Reading is not available in state $this")
24 internal open fun startWriting(): ReadWriteBufferState = error("Writing is not available in state $this")
25 internal open fun stopReading(): ReadWriteBufferState = error("Unable to stop reading in state $this")
26 internal open fun stopWriting(): ReadWriteBufferState = error("Unable to stop writing in state $this")
Sergey Mashkov86f70612017-07-25 10:59:44 +030027
Roman Elizarov469cad32017-08-15 15:54:56 +030028 object IdleEmpty : ReadWriteBufferState(EmptyByteBuffer, EmptyCapacity) {
Sergey Mashkov86f70612017-07-25 10:59:44 +030029 override val idle: Boolean get() = true
Sergey Mashkov86f70612017-07-25 10:59:44 +030030 override fun toString() = "IDLE(empty)"
Sergey Mashkov86f70612017-07-25 10:59:44 +030031 }
32
Roman Elizarov83762032017-08-08 19:58:40 +030033 class Initial(
34 backingBuffer: ByteBuffer,
35 reservedSize: Int = RESERVED_SIZE
36 ) : ReadWriteBufferState(backingBuffer, RingBufferCapacity(backingBuffer.capacity() - reservedSize)) {
37 init {
38 require(backingBuffer.position() == 0)
39 require(backingBuffer.limit() == backingBuffer.capacity())
40 }
41 override val writeBuffer: ByteBuffer = backingBuffer.duplicate() // defensive copy of buffer's state
42 override val readBuffer: ByteBuffer = backingBuffer.duplicate() // must have a separate buffer state here
43 // all other possible states
44 internal val idleState = IdleNonEmpty(this)
45 internal val readingState = Reading(this)
46 internal val writingState = Writing(this)
47 internal val readingWritingState = ReadingWriting(this)
48 // state transitions
Sergey Mashkov86f70612017-07-25 10:59:44 +030049 override fun startReading() = readingState
50 override fun startWriting() = writingState
Sergey Mashkov86f70612017-07-25 10:59:44 +030051 override val idle: Boolean get() = error("Not available for initial state")
Sergey Mashkov86f70612017-07-25 10:59:44 +030052 override fun toString() = "Initial"
53 }
54
Roman Elizarov83762032017-08-08 19:58:40 +030055 class IdleNonEmpty internal constructor(
56 val initial: Initial // public here, so can release initial state when idle
57 ) : ReadWriteBufferState(initial.backingBuffer, initial.capacity) {
58 override fun startReading() = initial.readingState
59 override fun startWriting() = initial.writingState
Sergey Mashkov86f70612017-07-25 10:59:44 +030060 override val idle: Boolean get() = true
Sergey Mashkov86f70612017-07-25 10:59:44 +030061 override fun toString() = "IDLE(with buffer)"
62 }
63
Roman Elizarov83762032017-08-08 19:58:40 +030064 class Reading internal constructor(
65 private val initial: Initial
66 ) : ReadWriteBufferState(initial.backingBuffer, initial.capacity) {
67 override val readBuffer: ByteBuffer get() = initial.readBuffer
68 override fun startWriting() = initial.readingWritingState
69 override fun stopReading() = initial.idleState
Sergey Mashkov86f70612017-07-25 10:59:44 +030070 override fun toString() = "Reading"
71 }
72
Roman Elizarov83762032017-08-08 19:58:40 +030073 class Writing internal constructor(
74 private val initial: Initial
75 ) : ReadWriteBufferState(initial.backingBuffer, initial.capacity) {
76 override val writeBuffer: ByteBuffer get() = initial.writeBuffer
77 override fun startReading() = initial.readingWritingState
78 override fun stopWriting() = initial.idleState
Sergey Mashkov86f70612017-07-25 10:59:44 +030079 override fun toString() = "Writing"
80 }
81
Roman Elizarov83762032017-08-08 19:58:40 +030082 class ReadingWriting internal constructor(
83 private val initial: Initial
84 ) : ReadWriteBufferState(initial.backingBuffer, initial.capacity) {
85 override val readBuffer: ByteBuffer get() = initial.readBuffer
86 override val writeBuffer: ByteBuffer get() = initial.writeBuffer
87 override fun stopReading() = initial.writingState
88 override fun stopWriting() = initial.readingState
Sergey Mashkov86f70612017-07-25 10:59:44 +030089 override fun toString() = "Reading+Writing"
90 }
91
Roman Elizarov469cad32017-08-15 15:54:56 +030092 object Terminated : ReadWriteBufferState(EmptyByteBuffer, EmptyCapacity) {
Sergey Mashkov86f70612017-07-25 10:59:44 +030093 override fun toString() = "Terminated"
94 }
Roman Elizarov83762032017-08-08 19:58:40 +030095}