Skip to main content

Overview

Instructions are the individual operations that threads execute. Each instruction has a type field and optional parameters. The execution engine processes instructions using a dispatcher pattern.

Instruction Types

All instruction types are defined in instructions.js:
instructions.js
export const Instructions = {
  ACQUIRE: "acquire", // Intentar tomar el mutex.
  WITHDRAW: "withdraw", // Retirar dinero de la cuenta.
  DEPOSIT: "deposit", // Ingresar dinero en la cuenta.
  RELEASE: "release", // Soltar el mutex.
  WAIT_SEM: "wait_sem", // Intentar tomar un token del semaforo.
  PRINT: "print", // Simular impresion de trabajo.
  SIGNAL_SEM: "signal_sem", // Liberar token del semaforo.
  WAIT_FOOD: "wait_food", // Cliente espera comida si aun no esta lista.
  EAT_FOOD: "eat_food", // Cliente consume el plato reservado.
  COOK_DISH: "cook_dish", // Chef prepara un plato.
  SIGNAL_FOOD: "signal_food", // Chef avisa que hay comida lista.
  ENTER_READ: "enter_read", // Lector intenta entrar al monitor en modo lectura.
  READ_BOOK: "read_book", // Lector lee el libro compartido.
  EXIT_READ: "exit_read", // Lector sale del monitor.
  ENTER_WRITE: "enter_write", // Escritor intenta entrar al monitor en modo escritura.
  UPDATE_CATALOG: "update_catalog", // Escritor actualiza catalogo.
  EXIT_WRITE: "exit_write", // Escritor sale del monitor.
  RUN_STAGE: "run_stage", // Corredor avanza en un tramo de la carrera.
  BARRIER_WAIT: "barrier_wait", // Corredor espera en checkpoint hasta que lleguen todos.
  BUILD_STAGE: "build_stage", // Trabajador construye una etapa de la casa.
  JOIN_THREAD: "join_thread", // Espera a que termine un hilo especifico.
  AWAIT_ALL: "await_all", // Espera a que termine un grupo de hilos.
  COMPLETE_HOUSE: "complete_house", // Marca entrega final de la casa.
  PETERSON_LOCK: "peterson_lock", // Robot intenta entrar a estacion compartida.
  USE_STATION: "use_station", // Robot usa la estacion critica.
  PETERSON_UNLOCK: "peterson_unlock", // Robot libera estacion compartida.
  END: "end", // Finalizar ejecucion del hilo.
};

Mutex Instructions

Used in the Bank Scenario to protect critical sections.

ACQUIRE

Attempts to acquire a mutex lock. Blocks if the mutex is already held.
{ type: Instructions.ACQUIRE }
Execution:
engine.js
case Instructions.ACQUIRE:
  if (mutex.acquire(thread)) {
    thread.nextInstruction();
    return `🔑 ${thread.name} entro en Seccion Critica`;
  }
  return `🔒 ${thread.name} esta esperando el Mutex`;
If the mutex is unavailable, the thread does NOT advance its program counter and will retry in the next step.

RELEASE

Releases a previously acquired mutex lock.
{ type: Instructions.RELEASE }
Execution:
engine.js
case Instructions.RELEASE:
  mutex.release(thread);
  thread.nextInstruction();
  return `🔓 ${thread.name} salio y libero el Mutex`;

Example: Mutex Protection

const instructions = [
  { type: Instructions.ACQUIRE },      // Enter critical section
  { type: Instructions.WITHDRAW, amount: 100 },  // Protected operation
  { type: Instructions.RELEASE },      // Exit critical section
  { type: Instructions.END }
];

Bank Instructions

Operations on a shared bank account.

WITHDRAW

Withdraws money from the shared account. Never allows negative balance.
{ type: Instructions.WITHDRAW, amount: 100 }
Parameters:
  • amount - Amount to withdraw (number)
Execution:
engine.js
case Instructions.WITHDRAW:
  const requested = Number(inst.amount) || 0;
  const allowed = Math.min(requested, Math.max(0, account.balance));
  account.balance -= allowed;
  thread.nextInstruction();

  if (allowed < requested) {
    return `⚠️ ${thread.name} pidio retirar $${requested}, pero solo se retiro $${allowed} (saldo insuficiente)`;
  }

  return `💸 ${thread.name} modifico el saldo: -$${allowed}`;

DEPOSIT

Deposits money into the shared account.
{ type: Instructions.DEPOSIT, amount: 150 }
Parameters:
  • amount - Amount to deposit (number)
Execution:
engine.js
case Instructions.DEPOSIT:
  account.balance += inst.amount;
  thread.nextInstruction();
  return `💵 ${thread.name} ingreso al saldo: +$${inst.amount}`;

Semaphore Instructions

Used in the Printer Scenario to manage limited resources.

WAIT_SEM

Attempts to acquire a semaphore token and printer. Blocks if none available.
{ type: Instructions.WAIT_SEM }
Execution:
engine.js
case Instructions.WAIT_SEM: {
  const printerIndex = ctx.semaphore.wait(thread, ctx.printers);
  if (printerIndex !== null) {
    thread.nextInstruction();
    return `🟢 ${thread.name} obtuvo Impresora-${printerIndex + 1}`;
  }
  return `⏳ ${thread.name} espera una impresora libre`;
}

PRINT

Simulates printing pages on the assigned printer.
{ type: Instructions.PRINT, pages: 5 }
Parameters:
  • pages - Number of pages to print (number)
Execution:
engine.js
case Instructions.PRINT: {
  const pages = Math.max(1, Number(inst.pages) || 1);
  const printerIndex = ctx.semaphore.getAssignedPrinter(thread);
  thread.nextInstruction();

  if (printerIndex === null) {
    return `⚠️ ${thread.name} no tiene impresora asignada`;
  }
  return `🖨️ ${thread.name} imprime ${pages} paginas en Impresora-${printerIndex + 1}`;
}

SIGNAL_SEM

Releases the semaphore token and printer.
{ type: Instructions.SIGNAL_SEM }
Execution:
engine.js
case Instructions.SIGNAL_SEM: {
  const printerIndex = ctx.semaphore.getAssignedPrinter(thread);
  if (printerIndex !== null && ctx.printers?.[printerIndex]) {
    const printer = ctx.printers[printerIndex];
    const pages = Math.max(1, Number(thread.jobPages) || 1);
    printer.completedJobs += 1;
    printer.totalPages += pages;
    printer.lastCompletedJob = { name: thread.name, pages };
  }

  const transfer = ctx.semaphore.signal(thread, ctx.printers);
  thread.nextInstruction();

  if (transfer.nextThread) {
    return `🔁 ${thread.name} libera Impresora-${printerIndex + 1} y la pasa a ${transfer.nextThread.name}`;
  }
  return `✅ ${thread.name} libera Impresora-${printerIndex + 1}`;
}

Example: Semaphore Usage

const instructions = [
  { type: Instructions.WAIT_SEM },     // Acquire printer
  { type: Instructions.PRINT, pages: 10 },  // Use printer
  { type: Instructions.SIGNAL_SEM },   // Release printer
  { type: Instructions.END }
];

Condition Variable Instructions

Used in the Restaurant Scenario for producer-consumer coordination.

WAIT_FOOD

Customer waits for food to be available.
{ type: Instructions.WAIT_FOOD }
Execution:
engine.js
case Instructions.WAIT_FOOD: {
  if (ctx.restaurant.availableDishes > 0) {
    ctx.restaurant.availableDishes -= 1;
    thread.hasReservedDish = true;
    thread.nextInstruction();
    return `🍽️ ${thread.name} recibio un plato y pasa a comer`;
  }

  thread.state = "blocked";
  thread.blockedBy = ctx.restaurant.foodCondition;
  ctx.restaurant.foodCondition.wait(thread);
  return `🪑 ${thread.name} espera comida en el restaurante`;
}

EAT_FOOD

Customer consumes their reserved dish.
{ type: Instructions.EAT_FOOD }

COOK_DISH

Chef prepares a dish.
{ type: Instructions.COOK_DISH }
Execution:
engine.js
case Instructions.COOK_DISH: {
  ctx.restaurant.availableDishes += 1;
  ctx.restaurant.totalCooked += 1;
  thread.nextInstruction();
  return `👨‍🍳 ${thread.name} preparo un plato (${ctx.restaurant.totalCooked}/${ctx.restaurant.mealsTarget})`;
}

SIGNAL_FOOD

Chef signals that food is ready, waking a waiting customer.
{ type: Instructions.SIGNAL_FOOD }
Execution:
engine.js
case Instructions.SIGNAL_FOOD: {
  const awakened = ctx.restaurant.foodCondition.signal();
  thread.nextInstruction();

  if (!awakened) {
    return `📣 ${thread.name} anuncio comida, pero no habia clientes esperando`;
  }

  awakened.state = "ready";
  awakened.blockedBy = null;
  return `🔔 ${thread.name} llamo a ${awakened.name}: comida lista`;
}

Monitor Instructions

Used in the Library Scenario for readers-writers synchronization.

ENTER_READ / EXIT_READ

Readers enter and exit the monitor in shared read mode.
{ type: Instructions.ENTER_READ }
{ type: Instructions.EXIT_READ }

READ_BOOK

Reads a book while holding read access.
{ type: Instructions.READ_BOOK, title: "Libro-1" }
Parameters:
  • title - Book title (string, optional)

ENTER_WRITE / EXIT_WRITE

Writers enter and exit the monitor in exclusive write mode.
{ type: Instructions.ENTER_WRITE }
{ type: Instructions.EXIT_WRITE }

UPDATE_CATALOG

Updates the library catalog (requires write access).
{ type: Instructions.UPDATE_CATALOG }
Execution:
engine.js
case Instructions.UPDATE_CATALOG: {
  ctx.library.catalogVersion += 1;
  ctx.library.totalWrites += 1;
  thread.nextInstruction();
  return `🗂️ ${thread.name} actualizo catalogo a version ${ctx.library.catalogVersion}`;
}

Barrier Instructions

Used in the Race Scenario for synchronization points.

RUN_STAGE

Runner advances through a race stage.
{ type: Instructions.RUN_STAGE, stage: "to-checkpoint" }
{ type: Instructions.RUN_STAGE, stage: "to-finish" }
Parameters:
  • stage - Stage identifier (string)

BARRIER_WAIT

Runner waits at checkpoint until all runners arrive.
{ type: Instructions.BARRIER_WAIT }
Execution:
engine.js
case Instructions.BARRIER_WAIT: {
  const result = ctx.race.barrier.arrive(thread);
  if (!result.passed) {
    return `🧱 ${thread.name} espera en el checkpoint (${ctx.race.barrier.waitingQueue.length}/${ctx.race.totalRacers - 1} en cola)`;
  }

  if (!thread.passedCheckpoint) {
    thread.passedCheckpoint = true;
    ctx.race.passedCheckpointCount += 1;
  }

  thread.nextInstruction();

  if (!result.opened) {
    return `✅ ${thread.name} cruza el checkpoint tras apertura de barrera`;
  }

  const releasedNames = result.released.map((t) => t.name).join(", ");
  return `🚦 ${thread.name} abrio barrera y libero a: ${releasedNames}`;
}

Thread Coordination Instructions

Used in the House Scenario for task dependencies.

BUILD_STAGE

Worker builds a construction stage over multiple ticks.
{ type: Instructions.BUILD_STAGE, stage: "Cimientos", duration: 3 }
Parameters:
  • stage - Stage name (string)
  • duration - Number of ticks required (number)
Execution:
engine.js
case Instructions.BUILD_STAGE: {
  const stage = inst.stage || "Etapa";
  const total = Math.max(1, Number(inst.duration) || 1);
  const progressMap = (thread.stageProgress ??= {});
  const current = (progressMap[stage] ?? 0) + 1;
  progressMap[stage] = current;

  if (current < total) {
    return `🧱 ${thread.name} construye ${stage} (${current}/${total})`;
  }

  if (ctx.house?.stages?.[stage]) {
    ctx.house.stages[stage].done = true;
  }
  thread.nextInstruction();
  return `🏗️ ${thread.name} termino ${stage}`;
}
BUILD_STAGE is the only instruction that executes over multiple ticks without advancing the program counter until completion.

JOIN_THREAD

Waits for a specific thread to finish.
{ type: Instructions.JOIN_THREAD, target: "Maestro-Cimientos" }
Parameters:
  • target - Name of thread to wait for (string)
Execution:
engine.js
case Instructions.JOIN_THREAD: {
  const target = inst.target;
  const ready = ctx.joinManager.join(thread, target);
  if (!ready) {
    thread.state = "blocked";
    thread.blockedBy = ctx.joinManager;
    return `⛓️ ${thread.name} espera join de ${target}`;
  }

  thread.nextInstruction();
  return `✅ ${thread.name} join cumplido con ${target}`;
}

AWAIT_ALL

Waits for multiple threads to finish.
{ type: Instructions.AWAIT_ALL, targets: ["Techador", "Instalador"] }
Parameters:
  • targets - Array of thread names to wait for (string[])

COMPLETE_HOUSE

Marks house construction as complete.
{ type: Instructions.COMPLETE_HOUSE }

Peterson’s Algorithm Instructions

Used in the Peterson Scenario for two-thread mutual exclusion.

PETERSON_LOCK

Attempts to enter critical section using Peterson’s algorithm.
{ type: Instructions.PETERSON_LOCK }
Execution:
engine.js
case Instructions.PETERSON_LOCK: {
  const id = Number(thread.petersonId);
  const entered = ctx.station.lock.lock(id);
  if (!entered) {
    thread.state = "blocked";
    thread.blockedBy = ctx.station.lock;
    return `🤖 ${thread.name} espera turno en estacion (turn=${ctx.station.lock.turn + 1})`;
  }

  thread.nextInstruction();
  return `🔐 ${thread.name} entro a estacion compartida`;
}
Requires thread.petersonId to be set to 0 or 1.

USE_STATION

Uses the shared station (critical section).
{ type: Instructions.USE_STATION }

PETERSON_UNLOCK

Exits critical section using Peterson’s algorithm.
{ type: Instructions.PETERSON_UNLOCK }

Control Flow Instructions

END

Marks thread as finished and wakes any threads waiting for it.
{ type: Instructions.END }
Execution:
engine.js
case Instructions.END:
  thread.state = "finished";
  if (ctx.joinManager) {
    const awakened = ctx.joinManager.markFinished(thread);
    awakened.forEach((waitingThread) => {
      waitingThread.state = "ready";
      waitingThread.blockedBy = null;
    });

    if (awakened.length > 0) {
      const names = awakened.map((t) => t.name).join(", ");
      return `🏁 ${thread.name} finalizo y desperto a: ${names}`;
    }
  }
  return `🏁 ${thread.name} finalizo sus tareas`;
Always end thread instruction sequences with END, or the engine will automatically mark the thread as finished when it runs out of instructions.

Instruction Composition

Instructions are composed into sequences that define thread behavior:
[
  { type: Instructions.ACQUIRE },
  { type: Instructions.WITHDRAW, amount: 100 },
  { type: Instructions.RELEASE },
  { type: Instructions.END }
]

Next Steps

Scenarios

Learn how scenarios compose instructions into complete simulations

Execution Engine

Understand how instructions are executed