@tysonnorris 

- for the `if delta < 0 =>`, I think the `s.setMaxPermits(5) // reduce max 
permits` match the case

- for the concurrent situations, I added below tests

```
  it should "set the max allowed permits while call release concurrently" in {
    (0 until 100).foreach { _ =>
      val s = new ForcibleSemaphore(32)
      s.tryAcquire(32) // 0 permits left

      (0 until 64).par.map{ i =>
        if ( i == 16)
          s.setMaxPermits(16) // force acquire 16 permits
        else
          s.release()
      }

      s.availablePermits shouldBe 47 // 0 - 16 + 63
    }

    (0 until 100).foreach { _ =>
      val s = new ForcibleSemaphore(32)
      s.tryAcquire(32) // 0 permits left

      (0 until 64).par.map{ i =>
        if ( i == 16)
          s.setMaxPermits(64) // release 32 permits
        else
          s.release()
      }

      s.availablePermits shouldBe 95 // 0 + 32 + 63
    }
  }

  it should "set the max allowed permits while call forceAcquire concurrently" 
in {
    (0 until 100).foreach { _ =>
      val s = new ForcibleSemaphore(32)

      (0 until 64).par.map{ i =>
        if ( i == 16)
          s.setMaxPermits(16) // force acquire 16 permits
        else
          s.forceAcquire()
      }

      s.availablePermits shouldBe -47 // 32 - 16 - 63
    }
    (0 until 100).foreach { _ =>
      val s = new ForcibleSemaphore(32)

      (0 until 64).par.map{ i =>
        if ( i == 16)
          s.setMaxPermits(64) // release 32 permits
        else
          s.forceAcquire()
      }

      s.availablePermits shouldBe 1 // 32 + 32 - 63
    }
  }

  it should "set the max allowed permits while call tryAcquire concurrently" in 
{
    (0 until 100).foreach { _ =>
      val s = new ForcibleSemaphore(32)

      (0 until 64).par.map{ i =>
        if ( i == 16)
          s.setMaxPermits(16) // force acquire 16 permits
        else
          s.tryAcquire()
      }

      s.availablePermits shouldBe ??? // not sure how many tryAcquire succeed
    }

    (0 until 100).foreach { _ =>
      val s = new ForcibleSemaphore(32)

      (0 until 64).par.map{ i =>
        if ( i == 16)
          s.setMaxPermits(64) // release 32 permits
        else
          s.tryAcquire()
      }

      s.availablePermits shouldBe ??? // not sure how many tryAcquire succeed
    }
  }
```

the first two tests will succeed while the last one will not, I believe the 
reason is that the `nonFairTryAcquireShared` will not change the state while 
`available - acquires < 0`, so we can not make sure a `tryAcquire` is success 
or not while `setMaxPermits` is in flight, any advice?

```
    @tailrec
    final def nonFairTryAcquireShared(acquires: Int): Int = {
      val available = getState
      val remaining = available - acquires
      if (remaining < 0 || compareAndSetState(available, remaining)) {
        remaining
      } else {
        nonFairTryAcquireShared(acquires)
      }
    }
```

[ Full content available at: 
https://github.com/apache/incubator-openwhisk/pull/3656 ]
This message was relayed via gitbox.apache.org for [email protected]

Reply via email to