ProgrammingPro #28: Thread Safety and Memory Safety in Python, C#/C++ , JS and more
Bite-sized actionable content, practical tutorials, and resources for programmers
"Probably the first website I ever built was copying the HTML code from yahoo.com and just editing it until it was David's website, and you know the more you do that, the more you actually start to learn the language yourself and you're able to start to build the stuff from scratch."
– David Karp, Founder of Tumblr (2018), Coding is Not Difficult
Welcome to this week’s issue of our programmer focused newsletter.
Today, we are covering some big announcements like Microsoft’s new C# Dev Kit and Docker, Neo4j, LangChain, and Ollama’s GenAI stack for developers that will let you harness the power of AI using the tools you are already familiar with.
We also take a quick look at Hyperscript, a user-friendly JavaScript alternative, and how Netfilx has been using Java.
In our tutorials and learning resources this week, we are focusing on strategies for thread safety and memory safety, to prevent data corruption, instability and unpredictable behavior in applications. Here are my top five picks:
How to Write Better Java Code using Pattern Matching and Sealed Classes
Safety vs Performance. A case study of C, C++, and Rust sort implementations
Singleton Design Pattern in Go: A Safe Approach to Global Variables
As always, we also have an exclusive excerpt for you on “Cancelling threads”, a new functionality in C++20, from the book C++ Programming for Linux Systems. So, scroll down and dive right in!
Stay awesome!
Divya Anne Selvaraj
Editor-in-Chief
PS: If you want us to find a tutorial for you the next time or give us any feedback, take the survey and as a thank you, you can download a free PDF of the book Mastering Defensive Security.
PPS: Want more Python stuff? Check out the archived first issue of PythonPro here!
🗞️News, 💡Opinions, and 🔎Analysis
Microsoft has introduced a C# Dev Kit extension for Visual Studio Code: This extension transforms Visual Studio Code into a robust .NET development environment which works well on macOS and can compete with Visual Studio for .NET development. Read to learn more about how the kit equips Visual Studio Code with essential tools, including the C# extension, AI-powered code completion, and more.
Docker, Neo4j, LangChain, and Ollama launch GenAI stack for devs: This stack simplifies the development of generative AI applications by providing pre-configured components, including large language models (LLMs) from Ollama, vector and graph databases from Neo4j, and LangChain framework. Read to learn more about how the stack simplifies setup, data loading, and query capabilities, allowing developers to create flexible knowledge graphs and generate diverse responses in various formats.
Intro to Hyperscript: Rethinking JavaScript: While it may not entirely replace JavaScript, Hyperscript, developed by Carson Gross, offers a fresh, efficient approach to web development, enhancing productivity and simplicity for developers. Read to learn more about this user-friendly JavaScript alternative, which simplifies front-end development, promotes self-documentation, and more.
QCon SF 2023:How Netflix Really Uses Java by Paul Bakker: At QCon SF 2023,Paul Bakker, a Java Champion and Java Platform expert at Netflix, challenged the myth that Netflix relies solely on RxJava microservices with Hystrix and Spring Cloud. Read to learn more about how Netflix's active development continues.
Python Developers Survey: Python 2 clings on for certain use cases: A recent survey of over 23,000 Python developers revealed that while Python 3 is dominant, Python 2 usage has increased slightly. Read to understand the extent to which Python 2 remains popular for certain use cases due to specific needs in areas like computer graphics, game development, and more.
Delivering Safe C++ - Bjarne Stroustrup Keynote at CppCon 2023: In his talk, Stroustrup addresses three major challenges: defining safety in various C++ contexts, guaranteeing this safety, and encouraging developers to write verified safe code. Watch if you are interested in achieving verified type-and-resource-safe C++ while minimizing runtime checks through abstractions.
🎓 Tutorials and Guides🤓
Implementing Structured Concurrency in C#:This article explains how to use Task Scopes to group and manage asynchronous tasks effectively, ensuring they all complete before considering the scope finished. Read to learn how to implement this approach, which is already prevalent in Kotlin, Swift, and Python, in C# using constructs similar to try-catch-finally blocks.
Implementing Discriminated Unions in C#: Discriminated unions help specify which types a function can return. Read to learn how to implement this functionality, which is already available in ASP.NET Core Minimal APIs, in C# using the OneOf package for a smoother coding experience.
How to Automate System Monitoring Using Python: System failures can disrupt operations and lead to financial losses. Read to learn how to automate system monitoring with Python using libraries like psutil and schedule to maintain IT infrastructure stability taking into account memory, network traffic, and other factors.
Metaclasses in Python – A brief introduction to Python class object and how it is created: This guide talks about how class objects are created, the role of new and init methods, and how to make classes callable with call. Read to discover the inner workings of metaclasses by explicitly specifying them.
Creating a custom user model in Django: This is a step-by-step guide, with access to the complete code on GitHub, will help you unlock the power of Django's custom user model to enhance authentication, streamline user information, and improve security. Read to learn how to create a custom user model in Django, use email as the unique identifier, create a custom User Model manager, and more.
How to compare signed and unsigned integers in C++20?: Comparing signed and unsigned integers in C++ can lead to unexpected outcomes. Read to learn how to make a safe comparison using "intcmp" functions which were introduced in the latest version.
How to Write Better Java Code using Pattern Matching and Sealed Classes: Pattern Matching simplifies data extraction and operations, with modern syntax being more concise and efficient. Sealed Classes, by restricting class hierarchies, improve code safety and organization. Read to learn how to combine these features in Java code for readability, type safety, reduced code duplication, and more.
How To Generate Spring Properties Documentation: The Spring Configuration Property Documenter Maven plugin extracts property documentation from your code and generates it in multiple formats like Markdown, HTML, and XML, making documentation closer to the code and more maintainable. Read to learn how to use this tool to enhance the documentation process for Spring projects.
Achieving Equality comparisons and sameness in JavaScript: JavaScript offers multiple equality comparison operations. Read to understand why these methods are essential for understanding JavaScript's equality behavior and how “===” is the recommended choice for most cases.
Web Storage Explained – How to Use local Storage and session Storage in JavaScript Projects: This article discusses the differences between session and local storage, their use cases, and built-in methods. Read for practical exercises to prevent data loss on page reload and clear storage and to learn how to use these features effectively to enhance your web apps' user experience.
🔑 Secret Knowledge: Learning Resources🔬
How Python Keeps Your Queues Thread-Safe: This article delves into the intricacies of Python's thread-safe queues, shedding light on the use of mutexes and the Global Interpreter Lock (GIL) to prevent race conditions. Read to understand the importance of thread safety when working with multiple threads and how Python's standard Queue implementation, based on deque, manages this safely.
Data Parallel C++ (Programming Accelerated Systems Using C++ and SYCL): This free to access book will help you master SYCL 2020 for C++ data-parallel programming through expert insights, practical advice, and GitHub code examples. Read if you are new to data-parallel programming or looking to optimize code for specific accelerators.
Safety vs Performance. A case study of C, C++, and Rust sort implementations: This analysis compared sort implementations in C, C++, and Rust, focusing on their safety and performance and found Rust to be the safest. Read if you want to use custom comparison functions with safe abstractions in libraries to prevent undefined behavior and improve code quality against benchmarks.
Concurrency and Thread Management in Embedded C++: This article talks about how concurrency boosts responsiveness in embedded systems and why C++shines in this field. Read to learn more about thread synchronization and communication to ensure safety, debug and test concurrent code, and more using real-time operating systems (RTOS) and thread management.
How To Compare Haskell Vs Rust: A Detailed Analysis: The choice between the two languages depends on project requirements, with Rust being suitable for system-level programming and embedded systems, and Haskell being the right choice for web development, data science, and theoretical work. Read to learn more about their unique features to make an informed language choice for your project.
What Is Thread-Safety in Java and How to Achieve It?: This article discusses 10 strategies for achieving thread-safety in Java including Immutable Implementations, Concurrent Collections, Atomic Objects, and more. Read to safely turbocharge your applications with multithreading by shielding against erratic behavior and unpredictable results.
Singleton Design Pattern in Go: A Safe Approach to Global Variables: Singleton ensures a single instance with controlled access, enhancing code quality and maintainability. Read to learn about a structured way to access a single point of truth in your application, making it thread-safe and minimizing resource wastage.
🧠 Expert insights from the Packt Community📚
Here’s an exclusive excerpt from “Chapter 6, Concurrent System Programming with C++” in the book C++ Programming for Linux Systems by Desislav Andreev and Stanimir Lukanov.
Canceling threads – is this really possible?
Before C++ 20 was released, this wasn’t quite possible. It was not guaranteed that std::thread was stoppable in the sense that there wasn’t a standard utility to halt the thread’s execution. Different mechanisms were used instead.
Stopping std::thread required cooperation between the main and worker threads, typically using a flag or atomic variable or some kind of messaging system.
With the release of C++20, there is now a standardized utility for requesting std::jthread objects to stop their execution. The stop tokens come to help. Looking at the C++ standard reference page about the definition of std::jthread we find the following:
“The class jthread represents a single thread of execution. It has the same general behavior asstd::thread, except that jthread automatically rejoins on destruction, and can be canceled/stopped in certain situations.”
We already saw that jthread objects automatically join on destruction, but what about canceling/stopping and what does “certain situations” mean? Let’s dig deeper into this.
First of all, don’t expect that std::jthread exposes some magical mechanism, some red button that stops the running thread when it is pressed. It is always a matter of implementation, how exactly your worker function is implemented. If you want your thread to be cancelable, you have to make sure that you have implemented it in the right way in order to allow cancellation:
#include<iostream>
#include<syncstream>
#include<thread>
#include<array>
using namespacestd::literals::chrono_literals;
int main() {
const auto worker{[](std::stop_token token,int num){
//{1}
while (!token.stop_requested()) { //{2}
std::osyncstream{std::cout}<< "Thread with id
" << num <<" is currently working.\n";
std::this_thread::sleep_for(200ms);
}
std::osyncstream{std::cout} <<"Thread with id " <<
num << " is nowstopped!\n";
}};
std::array<std::jthread, 3>my_threads{
std::jthread{worker, 0},
std::jthread{worker, 1},
std::jthread{worker, 2}
};
// Give some time to the other threads tostart
executing …
std::this_thread::sleep_for(1s);
// 'Let's stop them
for (auto& thread : my_threads) {
thread.request_stop(); // {3} - this isnot a
blocking call, it is just a request.
}
std::osyncstream{std::cout} < "Mainthread just
requested stop!\n";
return 0; // jthread dtors join them here.
}
Looking at the definition of our worker lambda function, we observe that it is now slightly reworked (marker {1}). It accepts two new parameters – std::stop_token token and int num. The stop token reflects the shared stop state that a jthread object has. If the worker method accepts many parameters, then the stop token must always be the first parameter passed.
It is imperative to ensure that the worker method is designed to be able to handle cancellation. This is what the stop token is used for. Our logic should be implemented in such a way that it regularly checks whether a stop request has been received. This is done with a call to the stop_requested() method of the std::stop_token object. Every specific implementation decides where and when these checks are to be done. If the code doesn’t respect the stop token state, then the thread can’t be canceled gracefully. So, it’s up to you to correctly design your code.
Luckily, our worker lambda respects the state of the thread’s stop token. It continuously checks whether a stop is requested (marker {2}). If not, it prints the thread’s ID and goes to sleep for 200ms. This loop continues until the parent thread decides to send stop requests to its worker threads (marker {3}). This is done by invoking the request_stop() method of the std::jthread object.
Here is the output of the program:
Thread with id 0 is currently working.
Thread with id 1 is currently working.
Thread with id 2 is currently working.
Thread with id 1 is currently working.
Thread with id 2 is currently working.
Thread with id 0 is currently working.
Thread with id 1 is currently working.
Thread with id 2 is currently working.
Thread with id 0 is currently working.
Thread with id 2 is currently working.
Thread with id 1 is currently working.
Thread with id 0 is currently working.
Thread with id 1 is currently working.
Thread with id 0 is currently working.
Thread with id 2 is currently working.
Main thread just requested stop!
Thread with id 1 is now stopped!
Thread with id 0 is now stopped!
Thread with id 2 is now stopped!
Now we know how we can stop the execution of a specific std::jthread using std::stop_token.
C++ Programming for Linux Systems by Desislav Andreev and Stanimir Lukanov was published in September 2023. To get a more comprehensive preview of the book's contents, read the first chapter available for free and buy the book here or signup for a Packt subscription to access the entire Packt digital library.
🛠️ HackerHub: Tools from GitHub⚒️
concurrent-map: A solution in Go to ensure efficient concurrent map operations, suitable for in-memory databases, with clear usage and contribution guidelines.
Easyloggingpp: a versatile single-header logging library for C++ applications, offering configurability, performance, and extensibility, with features like crash handling and compatibility with third-party libraries.
wuffs: a memory-safe language for safely handling untrusted file formats, emphasizing safety and speed, with compile-time checks and hermeticity, making it suitable for writing libraries used in projects like web browsers and operating systems.
hello-world.rs: a minimal and configurable Rust project boasting memory safety and blazing-fast performance, reducing the need for C code dependencies, with just one required library and efficient compile times.
amplication: An open-source platform for fast and secure Node.js app development with a user-friendly interface and team collaboration features.
📢 If your company is interested in reaching an audience of developers, software engineers, and tech decision makers, you may want to advertise with us.
We have an entire range of newsletters with focused content for tech pros. Subscribe to the ones you find the most useful here. Complete ProgrammingPro archives can be found here.
If you have any comments or feedback, take the survey!