Skip to main content

Overview

The Restaurant scenario simulates a chef preparing meals for customers who wait until their food is ready. This demonstrates the classic producer-consumer pattern using condition variables for efficient waiting and notification.

Real-World Problem

Imagine a restaurant where:
  • Customers arrive and wait for their meals
  • A chef prepares dishes one at a time
  • Customers should sleep (not busy-wait) until food is ready
  • The chef signals customers when each dish is prepared
This requires a mechanism where threads can efficiently wait for a condition to become true and be woken up when it changes.

Shared Resources

The shared resource is a restaurant state object containing:
  • availableDishes - Number of dishes ready to serve
  • totalCooked - Total dishes prepared by chef
  • totalEaten - Total dishes consumed by customers
  • foodCondition - Condition variable for synchronization
Protected by: Condition Variable (“ComidaLista”)

Synchronization Algorithm

This scenario uses a Condition Variable for producer-consumer coordination:
1

Customers Wait

Customer threads execute WAIT on the condition variable, blocking until food becomes available
2

Chef Produces

Chef thread cooks a dish, incrementing availableDishes
3

Chef Signals

Chef executes SIGNAL on the condition variable, waking up one waiting customer
4

Customer Consumes

Awakened customer decrements availableDishes and eats the meal

Scenario Setup

restaurantScenario.js
import { Thread } from "../core/thread.js";
import { Instructions } from "../core/instructions.js";
import { ConditionVariable } from "../core/conditionVariable.js";

export function createRestaurantScenario(engine, customerCount, mealsToCook) {
  const safeCustomers = Math.max(1, Number(customerCount) || 1);
  const safeMeals = Math.max(1, Number(mealsToCook) || 1);

  const restaurant = {
    availableDishes: 0,
    totalCooked: 0,
    totalEaten: 0,
    mealsTarget: safeMeals,
    foodCondition: new ConditionVariable("ComidaLista"),
  };

  // Add customer threads
  for (let i = 1; i <= safeCustomers; i++) {
    const customerInstructions = [
      { type: Instructions.WAIT_FOOD },
      { type: Instructions.EAT_FOOD },
      { type: Instructions.END },
    ];

    const customer = new Thread(`Cliente-${i}`, customerInstructions);
    engine.addThread(customer);
  }

  // Add chef thread
  const chefInstructions = [];
  for (let i = 0; i < safeMeals; i++) {
    chefInstructions.push({ type: Instructions.COOK_DISH });
    chefInstructions.push({ type: Instructions.SIGNAL_FOOD });
  }
  chefInstructions.push({ type: Instructions.END });

  const chefThread = new Thread("Chef", chefInstructions);
  engine.addThread(chefThread);

  return { restaurant, chefThread };
}

Configuration Options

ParameterDescriptionDefault
customerCountNumber of customer threadsMinimum 1
mealsToCookNumber of meals the chef preparesMinimum 1

Example Execution Flow

Initial: availableDishes = 0

Time 0:
  Cliente-1: WAIT_FOOD → BLOCKED (no food)
  Cliente-2: WAIT_FOOD → BLOCKED (no food)
  Cliente-3: WAIT_FOOD → BLOCKED (no food)
  Chef: Ready to cook

Time 1:
  Chef: COOK_DISH → availableDishes = 1
  Chef: SIGNAL_FOOD → Wake Cliente-1
  Cliente-1: UNBLOCKED → EAT_FOOD → totalEaten = 1

Time 2:
  Chef: COOK_DISH → availableDishes = 2
  Chef: SIGNAL_FOOD → Wake Cliente-2
  Cliente-2: UNBLOCKED → EAT_FOOD → totalEaten = 2
  Chef: END

Time 3:
  Cliente-1: END
  Cliente-2: END
  Cliente-3: Still BLOCKED (no more food)

Thread Instructions

Customer threads:
  1. WAIT_FOOD - Wait on condition variable until food is available
  2. EAT_FOOD - Consume a dish (decrement availableDishes)
  3. END - Terminate
Chef thread:
  1. COOK_DISH - Prepare one dish (increment availableDishes)
  2. SIGNAL_FOOD - Wake up one waiting customer
  3. Repeat for each meal
  4. END - Terminate
Condition variables enable efficient waiting. Instead of busy-waiting (repeatedly checking if food is ready), customers sleep until explicitly woken by the chef’s signal.

Producer-Consumer Pattern

This scenario demonstrates the classic pattern:
RoleThreadAction
ProducerChefCreates resources (dishes)
ConsumerCustomersConsumes resources (eats)
CoordinationCondition VariableSignals when resources available

Key Learning Points

  • Condition Variables: Enable threads to wait efficiently for conditions
  • Producer-Consumer: Chef produces, customers consume
  • Signal/Wait: Chef signals availability, customers wait for signal
  • Starvation: If meals < customers, some customers never eat
  • Efficiency: No busy-waiting; threads block until notified

Common Scenarios

✓ All customers get served
✓ No one waits unnecessarily