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
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
News
-
An All-Snap Version of Ubuntu is In The Works
Along with the standard deb version of the open-source operating system, Canonical will release an-all snap version.
-
Mageia 9 Beta 2 Ready for Testing
The latest beta of the popular Mageia distribution now includes the latest kernel and plenty of updated applications.
-
KDE Plasma 6 Looks to Bring Basic HDR Support
The KWin piece of KDE Plasma now has HDR support and color management geared for the 6.0 release.
-
Bodhi Linux 7.0 Beta Ready for Testing
The latest iteration of the Bohdi Linux distribution is now available for those who want to experience what's in store and for testing purposes.
-
Changes Coming to Ubuntu PPA Usage
The way you manage Personal Package Archives will be changing with the release of Ubuntu 23.10.
-
AlmaLinux 9.2 Now Available for Download
AlmaLinux has been released and provides a free alternative to upstream Red Hat Enterprise Linux.
-
An Immutable Version of Fedora Is Under Consideration
For anyone who's a fan of using immutable versions of Linux, the Fedora team is currently considering adding a new spin called Fedora Onyx.
-
New Release of Br OS Includes ChatGPT Integration
Br OS 23.04 is now available and is geared specifically toward web content creation.
-
Command-Line Only Peropesis 2.1 Available Now
The latest iteration of Peropesis has been released with plenty of updates and introduces new software development tools.
-
TUXEDO Computers Announces InfinityBook Pro 14
With the new generation of their popular InfinityBook Pro 14, TUXEDO upgrades its ultra-mobile, powerful business laptop with some impressive specs.