online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <stdatomic.h> #include <stdbool.h> #include <stdint.h> #include <string.h> #include <unistd.h> #include <sched.h> #define BUFFER_SIZE 32 #define NUM_PRODUCERS 2 #define NUM_CONSUMERS 2 #define ITEMS_PER_PRODUCER 10 #define EMPTY_SLOT -1 typedef struct { uint32_t head; uint32_t count; } queue_state; _Static_assert(sizeof(queue_state) == sizeof(uint64_t), "queue_state must be 64 bits"); static _Atomic int buffer[BUFFER_SIZE]; static _Atomic uint64_t state; static atomic_int num_producers = 0; static atomic_int sum_of_produced = 0; bool enqueue(int value) { while (1) { queue_state old_state = {.head = 0, .count = 0}; uint64_t old_state_val = atomic_load(&state); memcpy(&old_state, &old_state_val, sizeof(uint64_t)); if (old_state.count == BUFFER_SIZE) { return false; // Queue is full } uint32_t tail = (old_state.head + old_state.count) % BUFFER_SIZE; // Attempt to claim the empty slot int expected = EMPTY_SLOT; if (!atomic_compare_exchange_strong(&buffer[tail], &expected, value)) { continue; // Slot was filled by another thread, try // again } // Update the state queue_state new_state = old_state; new_state.count++; uint64_t new_state_val; memcpy(&new_state_val, &new_state, sizeof(uint64_t)); if (atomic_compare_exchange_weak(&state, &old_state_val, new_state_val)) { return true; } // If state update failed, revert the buffer change atomic_store(&buffer[tail], EMPTY_SLOT); } } bool dequeue(int *value) { while (1) { queue_state old_state = {.head = 0, .count = 0}; uint64_t old_state_val = atomic_load(&state); memcpy(&old_state, &old_state_val, sizeof(uint64_t)); if (old_state.count == 0) { return false; // Queue is empty } if (!atomic_compare_exchange_strong(&buffer[old_state.head], value, EMPTY_SLOT)) { continue; // Slot was emptied by another thread, try // again } queue_state new_state = old_state; new_state.count--; new_state.head = (old_state.head + 1) % BUFFER_SIZE; uint64_t new_state_val; memcpy(&new_state_val, &new_state, sizeof(uint64_t)); if (atomic_compare_exchange_weak(&state, &old_state_val, new_state_val)) { return true; } // If state update failed, revert the buffer change atomic_store(&buffer[old_state.head], *value); } } void * producer(void *arg) { int id = *(int *) arg; for (int i = 0; i < ITEMS_PER_PRODUCER; i++) { int value = id * 100 + i + 1; // Ensure we never produce EMPTY_SLOT while (!enqueue(value)) { sched_yield(); // Queue is full, yield and try again } printf("Producer %d enqueued: %d\n", id, value); usleep(rand() % 100000); // Sleep up to 0.1 seconds } atomic_fetch_sub(&num_producers, 1); printf("Producer %d finished\n", id); return NULL; } void * consumer(void *arg) { int id = *(int *) arg; while (1) { int value; if (dequeue(&value)) { printf("Consumer %d dequeued: %d\n", id, value); atomic_fetch_add(&sum_of_produced, value); usleep(rand() % 200000); // Sleep up to 0.2 seconds } else { if (atomic_load(&num_producers) == 0) { printf( "Consumer %d exiting: no more producers\n", id); break; } sched_yield(); // Queue is empty, yield and try again } } return NULL; } int main() { pthread_t producers[NUM_PRODUCERS]; pthread_t consumers[NUM_CONSUMERS]; int producer_ids[NUM_PRODUCERS]; int consumer_ids[NUM_CONSUMERS]; // Initialize state and buffer queue_state initial_state = {.head = 0, .count = 0}; atomic_store(&state, *(uint64_t *) &initial_state); for (int i = 0; i < BUFFER_SIZE; i++) { atomic_store(&buffer[i], EMPTY_SLOT); } // Set initial number of producers atomic_store(&num_producers, NUM_PRODUCERS); // Create producer threads for (int i = 0; i < NUM_PRODUCERS; i++) { producer_ids[i] = i; pthread_create(&producers[i], NULL, producer, &producer_ids[i]); } // Create consumer threads for (int i = 0; i < NUM_CONSUMERS; i++) { consumer_ids[i] = i; pthread_create(&consumers[i], NULL, consumer, &consumer_ids[i]); } // Wait for all threads to complete for (int i = 0; i < NUM_PRODUCERS; i++) { pthread_join(producers[i], NULL); } for (int i = 0; i < NUM_CONSUMERS; i++) { pthread_join(consumers[i], NULL); } int final_sum = atomic_load(&sum_of_produced); printf("Final sum of produced values: %d\n", final_sum); return 0; }

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue