A real-time commodity price monitoring system implementing the classic Bounded-Buffer Producer-Consumer Problem using System V IPC (Inter-Process Communication) mechanisms. This project demonstrates concurrent process synchronization using semaphores and shared memory.
- Overview
- Features
- System Architecture
- Prerequisites
- Installation
- Usage
- Implementation Details
- Commodities Supported
- Example Scenarios
- Technical Details
- License
- References
- Troubleshooting
- Authors
This project simulates a real-time commodity trading dashboard where multiple Producer processes generate live price updates for various commodities (GOLD, SILVER, CRUDEOIL, etc.), while a single Consumer process displays these prices in a dynamic, color-coded terminal dashboard.
The implementation showcases:
- Bounded-buffer synchronization using semaphores
- Shared memory for inter-process communication
- Normal distribution for realistic price simulation
- Real-time terminal UI with color indicators and trend arrows
- Concurrent price generation for up to 11 different commodities
- Configurable parameters: mean price (μ), standard deviation (σ), update interval
- Normal distribution price simulation for realistic market behavior
- Detailed logging with nanosecond-precision timestamps
- Graceful shutdown handling (SIGINT, SIGTSTP)
- Real-time dashboard displaying all commodity prices
- Moving average calculation (current + past 4 readings)
- Visual indicators:
- 🟢 Green ↑: Price increased
- 🔴 Red ↓: Price decreased
- 🔵 Blue: No change
- Alphabetically sorted commodity display
- Non-blocking updates using ANSI escape sequences
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Producer 1 │ │ Producer 2 │ ... │ Producer N │
│ (GOLD) │ │ (SILVER) │ │ (ZINC) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────┬───────┴────────────────────┘
│
▼
┌────────────────┐
│ Shared Memory │
│ (Circular │
│ Buffer) │
└────────┬───────┘
│
┌────────▼────────┐
│ Semaphores │
│ • Mutex │
│ • Empty Slots │
│ • Full Slots │
└────────┬────────┘
│
▼
┌────────────────┐
│ Consumer │
│ (Dashboard) │
└────────────────┘
- Mutex Semaphore: Ensures mutual exclusion for buffer access
- Empty Semaphore: Tracks available slots in the buffer
- Full Semaphore: Tracks filled slots ready for consumption
- Operating System: Linux/Unix (uses System V IPC)
- Compiler: g++ with C++17 support
- Build Tool: make
- System Libraries:
sys/shm.h(Shared Memory)sys/sem.h(Semaphores)sys/ipc.h(IPC mechanisms)
-
Clone the repository:
git clone <repository-url> cd producer-consumer-commodity-monitor
-
Compile the project:
make
This will generate two executables:
producer- Producer processconsumer- Consumer dashboard
-
Clean build artifacts (optional):
make clean
The consumer must be started first to initialize shared memory and semaphores:
./consumer <buffer_size>Example:
./consumer 50Launch one or more producers (in separate terminals or background processes):
./producer <COMMODITY> <mean_price> <std_dev> <interval_ms> <buffer_size>Parameters:
COMMODITY: Name of the commodity (max 10 characters)mean_price: Mean price (μ) for normal distributionstd_dev: Standard deviation (σ) for price varianceinterval_ms: Sleep interval between price updates (milliseconds)buffer_size: Size of bounded buffer (must match consumer's buffer size)
Examples:
# Gold prices: mean=$1800, σ=$20, update every 3 seconds
./producer GOLD 1800 20 3000 50 &
# Natural Gas: mean=$7.1, σ=$0.5, update every 200ms
./producer NATURALGAS 7.1 0.5 200 50 &
# Silver prices: mean=$25, σ=$1, update every 5.5 seconds
./producer SILVER 25 1 5500 50 &Use the provided make run target to start all 11 commodities simultaneously:
make runThis will launch the consumer and 11 producers with pre-configured parameters.
- Consumer: Press
Ctrl+Cto gracefully shutdown - Producers: Will automatically detect consumer shutdown and terminate
- Force Stop: Press
Ctrl+Z(handled by SIGTSTP)
struct Commodity {
char name[11]; // Commodity name
double price; // Current price
};
struct SharedMemory {
int in; // Write index (circular buffer)
int out; // Read index (circular buffer)
int size; // Buffer capacity
bool finished; // Shutdown flag
Commodity buffer[]; // Flexible array member
};// Wait (P operation / Down)
semWait(semId, SEM_INDEX);
// Signal (V operation / Up)
semSig(semId, SEM_INDEX);- Generate random price using normal distribution
- Log: "generating a new value"
- Wait on
EMPTY_SEM(ensure buffer has space) - Log: "trying to get mutex on shared buffer"
- Wait on
MUTEX_SEM(acquire lock) - Write commodity to buffer
- Log: "placing price on shared buffer"
- Update circular buffer index
- Signal
MUTEX_SEM(release lock) - Signal
FULL_SEM(indicate new data available) - Sleep for specified interval
- Repeat
- Initialize dashboard table
- Wait on
FULL_SEM(ensure data available) - Wait on
MUTEX_SEM(acquire lock) - Read commodity from buffer
- Update circular buffer index
- Signal
MUTEX_SEM(release lock) - Signal
EMPTY_SEM(free up slot) - Update price history and calculate moving average
- Determine price trend (up/down/unchanged)
- Update dashboard display with color coding
- Repeat
The system supports the following 11 commodities (alphabetically sorted):
- ALUMINIUM
- COPPER
- COTTON
- CRUDEOIL
- GOLD
- LEAD
- MENTHAOIL
- NATURALGAS
- NICKEL
- SILVER
- ZINC
# Terminal 1: Start consumer
./consumer 20
# Terminal 2: Start gold producer
./producer GOLD 1850 25 1000 20# Terminal 1: Start consumer
./consumer 40
# Terminal 2: Start producers
./producer GOLD 1850 25 1000 40 &
./producer SILVER 24 2 1500 40 &
./producer CRUDEOIL 75 5 800 40 &
./producer NATURALGAS 7.2 0.3 500 40 &# Low latency updates (100ms intervals)
./consumer 100
./producer GOLD 1850 10 100 100 &
./producer SILVER 24 1 100 100 &Prices follow a normal distribution N(μ, σ²):
std::normal_distribution<> dist(meanPrice, stdDev);
double price = dist(generator);Nanosecond precision using clock_gettime():
[MM/DD/YYYY HH:MM:SS.mmm]
Example: [12/31/2022 21:45:20.356]
Average of current price + past 4 readings (5-period SMA):
AvgPrice = (P₀ + P₁ + P₂ + P₃ + P₄) / 5
- Green (↑):
\033[;32m- Price increased - Red (↓):
\033[;31m- Price decreased - Blue ( ):
\033[;34m- No change or initial value
Generated using ftok():
key_t shmKey = ftok("/tmp", 11); // Shared memory key
key_t semKey = ftok("/tmp", 8); // Semaphore keyThis project is part of an academic assignment for educational purposes.
- Operating Systems: Three Easy Pieces - Remzi H. Arpaci-Dusseau
- System V IPC Documentation
- Producer-Consumer Problem (Bounded-Buffer Problem)
Solution: Start the consumer before any producers.
Solution: Ensure all producers use the same buffer size as the consumer.
Solution: Use ipcs to view and ipcrm to manually remove orphaned IPC resources:
# View IPC resources
ipcs
# Remove shared memory
ipcrm -m <shmid>
# Remove semaphores
ipcrm -s <semid>Solution: Check that producers are running and buffer size is adequate.
- @seifmaazouz - Consumer Implementation
- @AbdelrahmanEssam1007 - Producer Implementation
Operating Systems Lab (CC373) - Alexandria University