Skip to main content

How to Implement a Priority Queue in Batch Script

In standard queues (FIFO), items are processed in the exact order they arrive. A Priority Queue is a more advanced data structure where every item has an associated "Priority Level." In this system, items with a higher priority (e.g., "Critical Errors") are processed before items with a lower priority (e.g., "Routine Cleanups"), regardless of when they arrived in the queue.

In this guide, we will demonstrate how to build a priority queue using multi-level variable arrays.

The Strategy: Multiple Sub-Queues

The cleanest way to handle priorities in Batch without complex sorting is to create separate "Sub-queues" for each priority level (e.g., Level 1, 2, and 3).

  1. When adding an item, specify its priority.
  2. Add the item to the specific queue for that level.
  3. When processing, always check the Level 1 (Highest) queue first. Only if it is empty do you move to Level 2.
note

This multi-queue approach avoids the need for sorting entirely. Each priority level maintains its own FIFO order internally, and the processing loop simply drains higher-priority queues before moving to lower ones.

Implementation Script

@echo off
setlocal enabledelayedexpansion

:: 1. Initialize Counters for each priority level
set "P1_tail=0" & set "P1_head=1"
set "P2_tail=0" & set "P2_head=1"

echo --- PRIORITY QUEUE DEMONSTRATION ---

:: 2. ENQUEUE Items
:: Format: call :enqueue [Level] [Message]
call :enqueue 2 "Low priority: Scan temp files"
call :enqueue 1 "CRITICAL: Restart Database"
call :enqueue 2 "Low priority: Update docs"
call :enqueue 1 "CRITICAL: Resolve IP conflict"

echo.
echo Process starting... Checking priorities...
echo.

:: 3. Process Logic (Check Priority 1 first, then Priority 2)
:process_top
:: Check Priority 1 queue
if !P1_head! LEQ !P1_tail! (
call :dequeue 1
echo [EXEC P1] !result!
goto :process_top
)

:: If P1 is empty, check Priority 2 queue
if !P2_head! LEQ !P2_tail! (
call :dequeue 2
echo [EXEC P2] !result!
goto :process_top
)

echo.
echo [DONE] All queues flushed.

endlocal
pause
exit /b 0

:: ============================================
:: QUEUE FUNCTIONS
:: ============================================

:enqueue
:: Usage: call :enqueue [priority] "message"
set "lvl=%~1"
set "msg=%~2"
set /a "P!lvl!_tail+=1"
:: Use call to resolve the dynamic tail counter into the variable name
for %%t in (!P%lvl%_tail!) do set "P!lvl!_%%t=!msg!"
echo Enqueued [P%lvl%]: %msg%
exit /b

:dequeue
:: Usage: call :dequeue [priority] (result stored in !result!)
set "lvl=%~1"
if !P%lvl%_head! GTR !P%lvl%_tail! (
echo [ERROR] Priority %lvl% queue is empty.
set "result="
exit /b 1
)
:: Use for loop to resolve the dynamic head counter
for %%h in (!P%lvl%_head!) do (
set "result=!P%lvl%_%%h!"
set "P!lvl!_%%h="
)
set /a "P!lvl!_head+=1"
exit /b

Why Use a Priority Queue in Batch?

  1. System Maintenance: Ensuring that critical services are checked and restarted before time-consuming background tasks like disk defragmentation or log rotation.
  2. Emergency Response: If your script monitors several sensors or servers, a priority queue ensures that an "Offline" alert is fired before a "Low Disk Space" warning.
  3. Task Management: Organizing a list of deployment steps where "Pre-requisites" (Priority 1) must be confirmed before "Application Install" (Priority 2).

Visualizing the Process

  1. Arrival: Low(A), High(B), Low(C).
  2. Internal Storage:
    • Priority 1: [ B ]
    • Priority 2: [ A, C ]
  3. Processing order: B → A → C.

Important Considerations

warning

If Priority 1 items are constantly arriving, Priority 2 items will never be processed. This is called "Starvation." For very long-running scripts, consider periodically processing one low-priority item even when high-priority items exist to prevent indefinite delays.

  1. Starvation: If Priority 1 items are constantly arriving, Priority 2 items will never be processed. For very long-running scripts, you may need a system that periodically processes a low-priority item even if high ones exist.
  2. Memory: Every sub-queue uses environment memory. Be specific with your prefixes to avoid collisions.
  3. Maximum Levels: While this script uses two levels (1 and 2), you can easily expand it to 5 or 10 by adding more check blocks in the :process_top section.
tip

To add a third priority level, initialize P3_tail=0 and P3_head=1, then add a third if !P3_head! LEQ !P3_tail! block at the end of the :process_top section. The pattern scales to any number of levels.

Conclusion

Implementing a priority queue turns a basic script into a "Smart" task manager. By isolating critical tasks from routine operations, you ensure that your automation responds to urgent system needs with the highest possible speed. This architectural approach is essential for building mission-critical server monitoring tools and large-scale deployment frameworks that must handle varying levels of urgency in real-time.