1188. Design Bounded Blocking Queue - cocoder39/coco39_LC GitHub Wiki

1188. Design Bounded Blocking Queue

Option 1: condition

while not predicate():
    cv.wait()

==

wait_for(predicate)

quoted from java multithreading https://howtodoinjava.com/java/multi-threading/wait-notify-and-notifyall-methods/

if a notifier calls notify() on a resource but the notifier still needs to perform 10 seconds of actions on the resource within its synchronized block, the thread that had been waiting will need to wait at least another additional 10 seconds for the notifier to release the lock on the object, even though notify() had been called.
from threading import Condition
class BoundedBlockingQueue(object):

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.queue = collections.deque()
        self.condition = Condition()

    def enqueue(self, element: int) -> None:
        with self.condition:
            self.condition.wait_for(lambda: len(self.queue) < self.capacity)
            self.queue.append(element)
            self.condition.notifyAll()

    def dequeue(self) -> int:
        with self.condition:
            self.condition.wait_for(lambda: len(self.queue) > 0)
            val = self.queue.popleft()
            self.condition.notifyAll()
            return val

    def size(self) -> int:
        return len(self.queue) 

Option 2: semaphore

from threading import Semaphore

class BoundedBlockingQueue(object):

    def __init__(self, capacity: int):
        self.pushing = Semaphore(capacity)
        self.pulling = Semaphore(0)
        self.queue = collections.deque()

    def enqueue(self, element: int) -> None:
        self.pushing.acquire()
        self.queue.append(element)
        self.pulling.release()

    def dequeue(self) -> int:
        self.pulling.acquire()
        val = self.queue.popleft()
        self.pushing.release()
        return val

    def size(self) -> int:
        return len(self.queue)

python deque is thread safe. If deque is not thread safe, we should acquire a lock whenever performing append/popleft against deque

import threading

class BoundedBlockingQueue(object):
    def __init__(self, capacity: int):
        self.capacity = capacity
        
        self.pushing = threading.Semaphore(capacity)
        self.pulling = threading.Semaphore(0)
        self.editing = threading.Lock()
      
        self.queue = collections.deque()

    def enqueue(self, element: int) -> None:
      self.pushing.acquire()
      self.editing.acquire()
      
      self.queue.append(element)
      
      self.editing.release()
      self.pulling.release()

    def dequeue(self) -> int:
        self.pulling.acquire()
        self.editing.acquire()
        
        res = self.queue.popleft()
        
        self.editing.release()
        self.pushing.release()
        return res

    def size(self) -> int: