Guest User

Untitled

a guest
Dec 14th, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.87 KB | None | 0 0
  1. import kotlinx.coroutines.*
  2. import kotlinx.coroutines.channels.BroadcastChannel
  3. import kotlinx.coroutines.channels.broadcast
  4. import kotlinx.coroutines.sync.Mutex
  5. import kotlinx.coroutines.sync.withLock
  6. import kotlin.coroutines.CoroutineContext
  7.  
  8. class View(ui: CoroutineContext) {
  9. private val presenter = Presenter(
  10. ui = ui,
  11. io = Dispatchers.IO,
  12. view = this,
  13. interactor = Interactor()
  14. )
  15.  
  16. fun process(id: Int, value: Int) {
  17. presenter.given(id, value)
  18. }
  19.  
  20. fun render(id: Int, result: Int) {
  21. println("call[$id]view result: $result")
  22. }
  23.  
  24. fun render(id: Int, e: Throwable) {
  25. println("call[$id]view error: $e")
  26. throw e
  27. }
  28. }
  29.  
  30. class Interactor {
  31. private var count: Int = 0
  32.  
  33. suspend fun doSomething(value : Int): Int{
  34. println("interactor: ${++count}")
  35. delay(50)
  36. return value * value
  37. }
  38. }
  39.  
  40. data class HotInvocationContext(
  41. val mutex: Mutex = Mutex(),
  42. val map: MutableMap<String, BroadcastChannel<*>> = mutableMapOf()
  43. )
  44.  
  45. suspend fun <T> CoroutineScope.invokeHot(
  46. set: HotInvocationContext,
  47. key: String,
  48. block: suspend () -> T
  49. ): T {
  50. val (mutex, map) = set
  51. return mutex.withLock {
  52. if (map.contains(key)) {
  53. if (!map[key]!!.isClosedForSend) {
  54. println("channel reused")
  55. val broadcastChannel = map[key] as BroadcastChannel<T>
  56. return@withLock broadcastChannel.openSubscription()
  57. } else {
  58. println("channel has been closed")
  59. map.remove(key)
  60. }
  61. }
  62. println("channel created")
  63. val broadcastChannel = map.getOrPut(key) {
  64. broadcast {
  65. val result = block()
  66. mutex.withLock {
  67. send(result)
  68. map.remove(key)
  69. }
  70. println("channel sent")
  71. }
  72. } as BroadcastChannel<T>
  73. broadcastChannel.openSubscription()
  74. }.receive()
  75. }
  76.  
  77. class Presenter(
  78. ui: CoroutineContext,
  79. private val io: CoroutineDispatcher,
  80. private val view: View,
  81. private val interactor: Interactor
  82.  
  83. ): CoroutineScope {
  84. private val set: HotInvocationContext = HotInvocationContext()
  85. private val job: Job = Job()
  86. override val coroutineContext: CoroutineContext = job + ui
  87.  
  88. fun given(id: Int, value: Int) {
  89. launch {
  90. runCatching {
  91. withContext(io) {
  92. invokeHot(set, "doSomething$value") {
  93. interactor.doSomething(value)
  94. }
  95. }
  96. }
  97. .onSuccess { view.render(id, it) }
  98. .onFailure { view.render(id, it) }
  99. }
  100. }
  101. }
  102.  
  103. fun main() = runBlocking {
  104. val view = View(coroutineContext)
  105. repeat(10000) {
  106. delay(10)
  107. println("call[$it]")
  108. view.process(it, 5)
  109. }
  110. }
Add Comment
Please, Sign In to add comment