1117. Building H2O - cocoder39/coco39_LC GitHub Wiki

1117. Building H2O

Option 1 (Preferred): barrier + semaphore

Compared with option 2, option 1 has higher parallelism.

Imagining there is a waiting area which has 3 open slots. 2 hydrogens are allowed to enter it and 1 oxygen is allowed to enter it. Once all 3 slots get occupied, program gets resumed.

from threading import Barrier
from threading import Semaphore

class H2O:
    def __init__(self):
        self.barrier = Barrier(3)
        self.hSemaphore = Semaphore(2)
        self.oSemaphore = Semaphore(1)
        
    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:
        with self.hSemaphore:
            self.barrier.wait()
            # releaseHydrogen() outputs "H". Do not change or remove this line.
            releaseHydrogen()

    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:
        with self.oSemaphore:
            self.barrier.wait()
            # releaseOxygen() outputs "O". Do not change or remove this line.
            releaseOxygen()

Option 2: condition

from threading import Condition

class H2O:
    def __init__(self):
        self.condition = Condition()
        self.count = 0

    def hydrogen(self, releaseHydrogen: 'Callable[[], None]') -> None:
        with self.condition:
            self.condition.wait_for(lambda: self.count < 2)
            # releaseHydrogen() outputs "H". Do not change or remove this line.
            releaseHydrogen()
            self.count += 1
            self.condition.notifyAll()

    def oxygen(self, releaseOxygen: 'Callable[[], None]') -> None:
        with self.condition:
            self.condition.wait_for(lambda: self.count == 2)
            # releaseOxygen() outputs "O". Do not change or remove this line.
            releaseOxygen()
            self.count = 0
            self.condition.notifyAll()