Advertisement
Guest User

Untitled

a guest
Jun 28th, 2021
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 1.73 KB | None | 0 0
  1. @ExperimentalTime
  2. @ExperimentalCoroutinesApi
  3. private class RateLimiterImpl(override val permitsPerSecond: Int, override val timeSource: TimeSource) : RateLimiter {
  4.     init {
  5.         require(permitsPerSecond > 0) { "Rate must be > 0" }
  6.     }
  7.  
  8.     private val mutex = Mutex()
  9.     private val permitsLeft = atomic(permitsPerSecond)
  10.     private val timeFirstPermitAcquired = atomic<TimeMark?>(null)
  11.  
  12.     override suspend fun acquire() {
  13.         mutex.withLock {
  14.             if (permitsLeft.getAndUpdate { permits -> if (permits == 0) permitsPerSecond - 1 else permits - 1 } < 1) {
  15.                 delay(duration = timeUntilReset())
  16.  
  17.                 resetAndAcquire()
  18.             } else {
  19.                 timeFirstPermitAcquired.compareAndSet(null, timeSource.markNow())
  20.             }
  21.         }
  22.     }
  23.  
  24.     override fun tryAcquire(): Boolean {
  25.         val isAcquired = permitsLeft.getAndDecrement() >= 1
  26.  
  27.         if (!isAcquired && isTimeToReset()) {
  28.             return runBlocking {
  29.                 mutex.withLock {
  30.                     if (isTimeToReset()) {
  31.                         resetAndAcquire(); true
  32.                     } else {
  33.                         tryAcquire()
  34.                     }
  35.                 }
  36.             }
  37.         }
  38.  
  39.         if (isAcquired) {
  40.             timeFirstPermitAcquired.compareAndSet(null, timeSource.markNow())
  41.         }
  42.  
  43.         return isAcquired
  44.     }
  45.  
  46.     private fun resetAndAcquire() {
  47.         permitsLeft.value = permitsPerSecond - 1
  48.  
  49.         timeFirstPermitAcquired.value = timeSource.markNow()
  50.     }
  51.  
  52.     private fun isTimeToReset() = timeUntilReset().inWholeMilliseconds <= 0
  53.  
  54.     private fun timeUntilReset() = Duration.seconds(1).minus(timeFirstPermitAcquired.value!!.elapsedNow())
  55. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement