Skip to content

refactor(samples): replace pthreads with std::thread in multithreaded sample #13733

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 9 additions & 18 deletions Code Samples/Fib/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,29 @@
"configurations": [
{
"name": "(gdb) Launch",
"preLaunchTask": "build",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/fib.out",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"description": "Enable pretty-printing",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"logging": {
"engineLogging": false,
"trace": false
},
"windows": {
"program": "${workspaceRoot}/fib.exe",
"MIMode": "gdb",
"program": "${workspaceFolder}/fib.exe",
"miDebuggerPath": "<Path/To/GDB>" // Path to gdb on windows
},
"linux": {
"program": "${workspaceRoot}/fib.out",
"MIMode": "gdb"
},
"osx": {
"program": "${workspaceRoot}/fib.out",
"MIMode": "lldb"
"program": "${workspaceRoot}/fib.out"
}
}
]
}
}
82 changes: 48 additions & 34 deletions Code Samples/Fib/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -1,50 +1,64 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"label": "build (Unix)",
"type": "shell",
"command": "make",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
"problemMatcher": ["$gcc"],
"options": {
"cwd": "${workspaceFolder}"
},
"windows": {
"command": "${workspaceRoot}/build.cmd",
"args": [
"<Path/To/MinGW/Cygwin/Bin/Folder>", // Path to the bin folder containing g++ to compile
"fib.exe" // Output executable name
]
"detail": "Build using Makefile (Linux/macOS)"
},
{
"label": "build (Windows)",
"type": "shell",
"command": "g++ -std=c++11 -pthread -o fib.exe main.cpp thread.cpp",
"group": "build",
"problemMatcher": ["$gcc"],
"options": {
"cwd": "${workspaceFolder}"
},
"linux": {
"command": "g++",
"args": [
"-g",
"*.cpp",
"-lpthread",
"--std=c++11",
"-o",
"fib.out"
]
"detail": "Build using g++ (Windows/MinGW)",
"windows": {
"options": {
"shell": {
"executable": "cmd.exe",
"args": ["/C"]
}
}
}
},
{
"label": "clean (Unix)",
"type": "shell",
"command": "make clean",
"options": {
"cwd": "${workspaceFolder}"
}
},
{
"label": "clean (Windows)",
"type": "shell",
"command": "del /Q fib.exe",
"options": {
"cwd": "${workspaceFolder}"
},
"osx": {
"command": "g++",
"args": [
"-g",
"*.cpp",
"-lpthread",
"--std=c++11",
"-o",
"fib.out"
]
"windows": {
"options": {
"shell": {
"executable": "cmd.exe",
"args": ["/C"]
}
}
}
}
]
}
}
20 changes: 20 additions & 0 deletions Code Samples/Fib/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CXX := g++
CXXFLAGS := -std=c++11 -Wall -Wextra
SRCS := main.cpp thread.cpp
OBJS := $(SRCS:.cpp=.o)
TARGET := fib_sample

all: $(TARGET)

$(TARGET): $(OBJS)
$(CXX) $(OBJS) -o $@

%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@

clean:
rm -f $(OBJS) $(TARGET)




29 changes: 27 additions & 2 deletions Code Samples/Fib/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
# Fib
# Fibonacci Debugging Sample

This code sample is to show debugging. Update `launch.json` and `tasks.json` in the `.vscode` folder to use your setup to build and debug.
This sample demonstrates C++ debugging capabilities in VS Code using a multithreaded Fibonacci number generator.

## Features
- Modern C++ implementation using `std::thread`
- Cross-platform debugging configuration
- Multiple debugging scenarios:
- Breakpoint debugging
- Conditional breakpoints
- Watch expressions
- Crash investigation
- Debugger attachment

## Getting Started

### Prerequisites
- C++ compiler (g++/clang/MSVC)
- VS Code with C++ extension
- Debugger (gdb/lldb/MSVC debugger)

### Building
```bash
# Linux/macOS
make

# Windows (MinGW)
g++ -std=c++11 -pthread -o fib.exe main.cpp thread.cpp
2 changes: 0 additions & 2 deletions Code Samples/Fib/build.cmd

This file was deleted.

111 changes: 72 additions & 39 deletions Code Samples/Fib/main.cpp
Original file line number Diff line number Diff line change
@@ -1,58 +1,91 @@
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#include <thread>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <atomic>
#include <chrono>
#include <csignal>
#include <unistd.h> // Required for getpid()
#include "thread.h"

#define THREAD_COUNT 10

static char block[] = "--block";
int test = 0;
static constexpr char block[] = "--block";
static constexpr char crash[] = "--crash";
static constexpr char test_flag[] = "--test";
std::atomic<int> test_count{0}; // Thread-safe counter
volatile std::sig_atomic_t g_signal_status = 0;

void signal_handler(int signal) {
g_signal_status = signal;
}

int main(int argc, char **argv)
{
srand(time(NULL));
// Register signal handler for clean interruption
std::signal(SIGINT, signal_handler);

static char pidText[] = "PID: ";
std::string helpText = "Attach a debugger and execute 'set foo=0' to continue";
char helloText[] = "Hello World!";
// Initialize random seed
std::srand(static_cast<unsigned>(std::time(nullptr)));

std::cout << helloText << std::endl;
std::cout << "Hello World!" << std::endl;

pthread_t threads[THREAD_COUNT];
if (argc == 2) {
if (std::strcmp(block, argv[1]) == 0) {
std::cout << "Attach a debugger and set foo=0 to continue" << std::endl;
std::cout << "Process ID: " << getpid() << std::endl;

if (argc == 2 && !strcmp(block, argv[1]))
{
std::cout << helpText << std::endl;
volatile int foo = 1;
while (foo)
;
volatile int foo = 1;
while (foo && g_signal_status == 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Waiting... (press Ctrl-C to quit)" << std::endl;
}
return 0;
}
else if (std::strcmp(crash, argv[1]) == 0) {
std::cout << "Triggering intentional crash..." << std::endl;
volatile int foo = 0;
volatile int bar = 1 / foo; // Guaranteed crash
(void)bar; // Suppress unused-variable warning
return 1; // Unreachable after crash
}
else if (std::strcmp(test_flag, argv[1]) == 0) {
std::cout << "Running in test mode" << std::endl;
// Add any test-specific code here
}
}

if (argc == 2 && !strcmp("--crash", argv[1]))
{
int foo = 0;
int bar = 1 / foo;
}
// Thread management
std::vector<std::thread> threads;
threads.reserve(THREAD_COUNT);

for (int i = 0; i < THREAD_COUNT; i++)
{
std::cout << "Test " << i << std::endl;
pthread_create(&threads[i], NULL, &thread_proc, NULL);
}
try {
// Create and launch threads
for (int i = 0; i < THREAD_COUNT; ++i) {
std::cout << "Launching thread " << i << std::endl;
threads.emplace_back(thread_proc);
}

for (int i = 0; i < THREAD_COUNT; i++)
{
pthread_join(threads[i], NULL);
test++;
// Join all threads
for (auto& t : threads) {
if (t.joinable()) {
t.join();
test_count.fetch_add(1, std::memory_order_relaxed);
}
}
}
catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
for (auto& t : threads) {
if (t.joinable()) {
t.detach();
}
}
return 1;
}

std::cout << "All threads exited!" << std::endl;

return 1;
std::cout << "\nAll " << test_count.load() << " threads completed successfully!" << std::endl;
return 0;
}
Loading