Developing concurrent programs with Pony
Horse Power

© Lead Image © Aleksandr Frolov, 123RF
Pony, an object-oriented programming language with static typecasting, trots down well-mapped paths to deliver secure, high-performance code for concurrent applications.
The still young Pony [1] programming language uses the actor model [2] and capabilities [3] to make deadlocks and data races things of the past. In this article, I take Pony for a test ride with an example application that, once it has compiled successfully, logs the consumption of paint and reports the results in a single line.
Figure 1 revisits the problems of concurrent programming in C and C++. To improve performance, the hypothetical program outsources tasks to concurrent threads that access the shared memory area. Locks manage access to prevent different threads editing data simultaneously, falsifying each other's results in the process, and generating race conditions. Nothing good results when programming errors interact and create deadlocks.
Table 1 summarizes the problems associated with implementation across various languages. The comparison with Java is inevitable, because the language offers one of the most successful enhancements of the C and C++ method. A comparison with Rust [4] is also appropriate, because the new kid in town also tries to generate secure and fast code for concurrent applications.
Table 1
Feature Comparison
Language Feature | C/C++ | Java | Rust | Pony |
---|---|---|---|---|
AoT Compilation |
Yes |
No* |
Yes |
Yes |
Memory Secure |
No |
Yes |
Yes |
Yes |
Type Secure |
No |
Yes |
Yes |
Yes |
Avoids Race Conditions |
No |
No |
Yes |
Yes |
Avoids Deadlocks |
No |
No |
No |
Yes |
Actor-Based |
No |
No |
No |
Yes |
*Officially as of Java 9 [5]. |
||||
Except for dynamic loading of classes [6]. |
Both Pony and Rust compile programs ahead of time (AoT) to create executable binary code. The method saves time because the languages identify and rule out type conflicts in advance. Java, on the other hand, usually first converts source code to non-executable bytecode, which a virtual machine (VM) executes and monitors. Pony and Java both leave memory management to a garbage collector, which Pony integrates into the run-time environment of the compiler results because it lacks a VM.
Actor Model
Pony programs are always free of data races and deadlocks through the agency of actors. As Figure 2 shows, the model does without a shared memory area and therefore does not need to use locks. Because internally the threads (aka actors) work sequentially, data races could theoretically still occur between the competing actors; however, applications mutually exchange application data through asynchronous communications. The sender deletes all pointers to variable data before sending, which also successfully prevents data races in this scenario.

Behaviors (asynchronous functions) are used as mailboxes for incoming messages, which Pony calls like normal methods but runs asynchronously. The actor thus continues its work sequentially. The Pony developers did not create the actor model; the programming languages Erlang, Io, D, and Scala also use it.
Installation
The current release of Pony [7] can be installed using the commands in Listing 1 on a 64-bit Debian system. The first line integrates the packet source into the /etc/apt/sources.list
file. The second line updates the Debian package database, and the third line installs Pony. There is no Debian package for the i386 architecture; a manual compile is needed in this case.
Listing 1
Installation on Debian 8
Listing 2 shows the directory tree of the sample application. If you change to the project directory and compile the program with ponyc
, the result is the binary executable, as shown in Figure 3, which you can launch with the ./blue-horses
command.
Listing 2
The .pony Files
The main.pony
file is the entry point for the Pony program (Figure 4). It uses the class from the resource.pony
file to create paint stocks for the primitives (colors) from primitives.pony
and presents these to the actor of the Painter
type from painter.pony
. The actor processes the quantity of paint and reports its consumption in the form of a report to main.pony
.

Classes
Pony summarizes application data in classes, as the Resource
class illustrates in the example in Listing 3, which stores paint types and their respective stock. The class
keyword introduces the class in line 1, and line 2 declares the public field name
of the user-defined Paint
type, which line 6 in Listing 4 again picks up. Thanks to the let
keyword, the field can only be written to once, in contrast to a field initiated as var
. The class stores the paint types and the respective stock.
Listing 3
resource.pony
Listing 4
primitives.pony
Line 3 of Listing 3 defines the private _amount
field as an integer data type and sets its value to
. Private field names are prefixed by an underscore, and only the owning class instance can access them. The constructor of the Resource
class introduces the new
keyword in line 5. The parameter list follows in create()
. The name'
variable field is a pointer to an object of the Paint
type. The next line then saves the name
field permanently as an instance of the class.
The fun
keyword introduces the method declarations for level()
and fill()
(lines 8 and 11). If the parameter list is followed by a colon, the type of the return value follows. For level()
, it is integer type U64
from the private _amount
field.
The value of the expression in the last line of a method is usually its return value, although the use of return
lets developers close methods prematurely. The fill()
method (line 11) increments the value of _amount
by 1
.
Because of the ref
specification in line 11, the method requires write access for a pointer to an instance of the Resource
class. These rights are granted by reference capabilities, which I talk about later; however, before I get to that, I'll look at primitives, which are similar to classes.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Direct Download
Read full article as PDF:
Price $2.95
News
-
Titan Linux is a New KDE Linux Based on Debian Stable
Titan Linux is a new Debian-based Linux distribution that features the KDE Plasma desktop with a focus on usability and performance.
-
Danielle Foré Has an Update for elementary OS 7
Now that Ubuntu 22.04 has been released, the team behind elementary OS is preparing for the upcoming 7.0 release.
-
Linux New Media Launches Open Source JobHub
New job website focuses on connecting technical and non-technical professionals with organizations in open source.
-
Ubuntu Cinnamon 22.04 Now Available
Ubuntu Cinnamon 22.04 has been released with all the additions from upstream as well as other features and improvements.
-
Pop!_OS 22.04 Has Officially Been Released
From the makers of some of the finest Linux-powered desktop and laptop computers on the market comes the latest version of their Ubuntu-based distribution, Pop!_OS 22.04.
-
Star Labs Unveils a New Small Format Linux PC
The Byte Mk I is an AMD-powered mini Linux PC with Coreboot support and plenty of power.
-
MX Linux Verison 21.1 “Wildflower” Now Available
The latest release of the systemd-less MX Linux is now ready for public consumption.
-
Microsoft Expands Their Windows Subsystem for Linux Offerings With AlmaLinux
Anyone who works with Windows Subsystem for Linux (WSL) will now find a new addition to the available distributions, one that’s become the front-runner replacement for CentOS.
-
Debian 11.3 Released wIth Numerous Bug and Security Fixes
The latest point release for Debian Bullseye is now available with some very important updates.
-
The First Alpha of Asahi Linux is Available
Asahi Linux is the first distribution to fully support Apple Silicon and is now available for testing.