This article provides a brief overview of the Haiku operating system from a programmer’s point of view, with sample code for an inter-application communication application. The Haiku API is simple and powerful and by the end of this article you will be able to use a variety of objects to write your own Haiku applications. Some C or C++ coding experience is useful.
Haiku Overview
Haiku is the open source reincarnation of the advanced Be operating system, BeOS. The Haiku project is now 10 years old and is readying its third Alpha release. This article will provide a brief overview of the Haiku architecture from a developer’s perspective and provide an application as an example for how a number of the interesting Haiku objects can work together to provide some sophisticated results.
For anyone who might be new to Haiku, here are some features:
- Pervasive multithreading
- A hybrid microkernel
- A single, clean, orthogonal API
- A native, mature windowing system
- An advanced, journaling, database file system
- Decent and growing hardware support
The original BeOS architecture was designed and written by a small development team over 10 or so years. It was designed to be a highly responsive, developer-friendly, personal operating system. It was written in C++ as a series of programmer-accessible objects. The API is written in C++ and is fairly easy to learn and work with . Much but not all of Haiku is documented online in the BeBook. A great set of introductory Haiku programming lessons can be found here, Learning to Program With Haiku. And additional source code examples can be downloaded here, BeOS sample code.
What does it mean when you have a great API with lots of multithreading built in? It means Haiku lets you build up some pretty advanced functionality fairly quickly, using only standard parts and a little bit of know-how. This article will take you through the design of a small program that does exactly that. Using the BLooper, BApplication, BRoster, BMessenger, BResources, and BGameAudio objects, we will create an application that spawns multiple instances of itself, where each instance can communicate with any other instance. But first, let’s take a quick overview of how Haiku works.
Haiku Architecture Overview
Haiku is based around client/server architectures, where applications are clients to functional servers, and the functional servers are in turn clients to the kernel, at the lowest level.
You as the developer write Haiku applications using the C++ class libraries. Applications can be simple command line programs, or sophisticated multi-windowed, multi-threaded affairs.
The functional servers that run on top of the kernel include:
- the application server
- the roster
- the network server
- the media server
- the media addon server
- the input server
- the print server
Each server runs in its own protected memory space, and together with the other servers implement much of the functionality available through the C++ API . If the concept of a server embedded in an operating system seems confusing, just think of it as a ‘subsystem’. You don’t actually have to know how it works to make it work. The Haiku API as a whole is divided into ‘kits’. These help organize the various object hierarchies into a classification that makes sense. The most important kits include:
- Application kit
- Interface kit
- Device kit
- Game kit
- Media kit
- Network kit
- Storage kit
- OpenGL kit
- Kernel kit
The Haiku kernel provides the basic operating system functions that the servers depend on. These functions include: multi-threading, multiple processors/multiple cores, preemptive multitasking, memory protection, virtual memory, semaphores, loadable drivers, shared libraries, and process scheduling. The scheduler was designed from inception to support multithreading as well as multiple processors. These features are intrinsic to Haiku and are the heart and soul of the Haiku API. You get these features for free when you use the API. For instance, our sample application will spawn 4 instances of itself, and each instance can run on its own CPU, with no explicit coding needed.
The application server is the first server that applications interface with. It is an instance of the BApplication C++ class that gets things started. The application server handles window management, graphics rendering, user interface interaction, event handling and more. An exceptional feature of Haiku that sets it apart from other operating systems is the fact that every window has, by default, two separate threads. One thread for graphic updates, and a second thread for user interaction. One thread runs inside the application server, and the other inside the application. This allows visual updates to occur completely separately from IO. This is a major contributing factor to the overall responsiveness of Haiku. It also means that every Haiku application with a window is both multithreaded, and supports multiprocessing by default. More threads can be spawned as needed, and Haiku natively supports the POSIX threads interface. This solves the common problem of applications becoming unresponsive during disk, CD, or network activities.
The Storage Kit provides access to the BFS file system, which has basic database functionality built in. The storage server gives you direct access to directories, files, indexes, and add/update/delete notifications that you can design. This saves you the effort of either writing your own database functions, or having to use a 3rd party library. The Haiku mail system uses the these functions to store emails. The result is that your email storage is limited only by the size of your hard disk. Another great feature is the ‘live’ search mechanism built into the file system. And once registered, you can receive continuous updates for searches matching your query criteria. Since common file attributes are automatically indexed, file system searches are very quick.
The network server provides inetd and configuration, such as DHCP. The network server was recently extended to support WEP wifi with encryption. Haiku includes applications for ftp, ftpd, telnet, as well as the poorman web server. The diner and Cherokee web servers are also available with many more Haiku-specific features.
The media server is the backbone for processing multimedia streams. It was designed to provide low latency access to audio, video, and image data types. The server manages the multimedia streams through a pipeline of buffers that are dispatched to data handlers. Each handler can hook into a media stream. Once it has done so, a handler can read or change the media stream in the pipeline. Buffers are implemented as shared memory, and are accessible by multiple applications without the need to copy the buffers. The media server can also synchronize different media streams by means of a global scheduling object. This is vital for processing video and audio together.
Application Fundamentals
At the core of any Haiku GUI application are the following objects: BApplication, BWindow, BView, BMessage, and BLooper. Each BLooper has a thread that acts as an event loop, where messages are handled. BApplication and BWindow are both derived from BLooper and so they each have a thread that handles messages. This is how window updates and IO are handled separately.
When an application is run in Haiku, it’s BApplication object is created. This starts the application’s main thread and event loop. As you will see in the MessageDemo code, it is at this point that an application can send and receive messages. Once the application thread is started, the application can create windows, which also create threads with event loops. Once a window is created and displayed, it can send and receive messages, which are generally related to user interactions, such as mouse or keyboard events.
BMessage is used to encapsulate Haiku messages. At a minimum, a BMessage must have a unique identifier, also known as the ‘what’ of a message:
enum { M_ABOUT_REQUESTED = 'abrq' }; BMessage *msg = new BMessage(M_ABOUT_REQUESTED);
BMessage also has the capability to pass an arbitrary amount of additional data in a message. BMessage provides a number of member functions for packing or ‘flattening’ various data into a message, and for finding, or ‘unflattening’ the data after it is received.
Messages are used for communication between applications, windows, and threads, for drag-and-drop, and for accessing the clipboard.
BMessenger is used to send a message to a target, which is a BLooper. Within a simple application or window, you can simply call SendMessage with a message you want, for example:
SendMessage(B_QUIT_REQUESTED);
This puts the B_QUIT_REQUESTED message in the message queue of the application or the window, to be handled in MessageReceived(). In order to send messages between applications, you have to uniquely identify the receiving application. To do this you need to know the application’s signature, as defined in the BApplication initialization:
BApplication("application/x-vnd.dw-MessDemo1");
If you are sending a message to one of several instances of an application, as we are, you must differentiate between application instances by using its team_id:
BMessenger(const char* signature, team_id team, status_t* error);
Let’s talk about MessageDemo
Message Demo demonstrates inter application messaging, and uses a number of interesting Haiku objects.
When launched, MessageDemo spawns 5 instances of itself. The 5th instance sends the A_GET_CONNECTED message to the first four and then terminates. The other four display themselves and take user input. Upon receipt of the A_GET_CONNECTED message each instance does the following:
- Retrieves the identifying team_id for each of the instances
- Moves itself to a quadrant of the screen
- Sets its window title
When the applications are displayed, each one displays 4 buttons, each button corresponds to one of the four applications. When you click on button 1, the M_PLAY_SOUND message is sent to Application 1. When Application 1 receives that message it plays its corresponding sound.
That’s what it does, let’s look at the code.
The first thing we do is subclass BApplication in App.h so we can add our own App and MessageReceived methods:
class App : public BApplication { public: App(void); void MessageReceived(BMessage *msg);; };
In our App method we use the global be_roster to fill list with apps that match the application signature specified by mySig. Each application instance will spawn another, and rerun this same code. CountItems will increase until there are 5 app instances. When there are 5, the 5th instance will use Broadcast() to send the A_GET_CONNECTED message to every application running. It will be ignored by every app except MessDemo. Messaging in Haiku is efficient so there’s no performance hit.
be_roster->GetAppList((const char *)mySig, list); if (list->CountItems() < 5){ // spawn new app instance fprintf(stderr, "Launching another appn"); be_roster->Launch(mySig); } else { // broadcast to all apps BMessage msg(A_GET_CONNECTED); status = be_roster->Broadcast(&msg); fprintf(stderr, "Got 5 apps, quittingn"); PostMessage(B_QUIT_REQUESTED); }
MessageDemo needs its own version of App::MessageReceived. This is because in Haiku the Application object has one event loop thread, and each Window has another. In MessDemo, the application receives the user generated messages and must pass them on to the Window to be processed. All other messages are sent to the application object for standard processing.
be_app is another ‘built-in’ Haiku global. Be_app always points to the current application object. In this case we use it to get the first window. In MessDemo the first window is also the only window, so things are simple. We use PostMessage() to send the message to the window.
switch (msg->what){ case A_GET_CONNECTED: fprintf(stderr,"MD: Get Connectedn"); case M_PLAY_SOUND:{ fprintf(stderr,"passing msg to the window's handlern"); be_app->WindowAt(0)->PostMessage(msg); break; } // Quit all instances of App case B_QUIT_REQUESTED: // pass messages on to App's handler default: BApplication::MessageReceived(msg); break; }
OK, let’s say we click on button 2. When we go into the MessageReceived method for MainWindow, we see that the event handler code for that button is this:
// send remote message to App 2 if ((err = bmsg2->SendMessage(M_PLAY_SOUND)) != B_OK){ fprintf(stderr,"App2: failure in SendMessage - %sn", strerror(err)); PostMessage(B_QUIT_REQUESTED); } else { fprintf(stderr, "Sent msg to App 2n"); }
bmsg2 is a BMessenger object that was already initialized to application instance 2 using the application signature and the team_id:
bmsg2 = new BMessenger(mySig, team_id2, &err);
BMessenger object uses SendMessage() to send the M_PLAY_SOUND message to the BLooper specified by the mySig application signature and the team_id for application 2. That message is sent to the BLooper for application instance 2, which then passes it on to the window, where the event handler plays the second audio resource.
MessageDemo uses the BSimpleGameSound object to play the wav or mp3 audio files.
The array of audio files is defined as:
BSimpleGameSound *Sounds[4]; gs_audio_format format;
Format is initialized here:
format.frame_rate = 22050; // CD quality format.channel_count = 1; // mono format.format = 0x11; // unsigned 8-bit format.byte_order = 1; format.buffer_size = 0;
The audio files are then read in from the resource file:
//load the sound data from the BResource and create array of
//BSimpleGameSound objects for (i=0; i < 4; i++){ err = res->GetResourceInfo(B_RAW_TYPE, i, &Name, &Size); if (!err){ fprintf(stderr, "Can't read audio resource from resource file - %sn",strerror(err)); PostMessage(B_QUIT_REQUESTED); break; } const void *Data = res->LoadResource(B_RAW_TYPE, i, &Size); Sounds[i] = new BSimpleGameSound(Data, Size, &format); fprintf(stderr,"nNumSounds = %dn",i); } //check to see if the last sound object was initialized int result = Sounds[3]->InitCheck(); if (result != B_OK){ fprintf(stderr,"Problem starting sound device - %sn",strerror(result)); PostMessage(B_QUIT_REQUESTED); }
When the application gets the M_PLAY_SOUND message all it has to do is run InitCheck() to validate, and then play the file:
if ((err=Sounds[whoami-1]->InitCheck()) != B_OK){ fprintf(stderr,"bad audio InitCheck - %s",strerror(err)); } else Sounds[whoami-1]->StartPlaying();
MessDemo also has a File/Quit menu item and implements some spiffy multi-application quit code. In this case, when you select quit for one application, they all quit:
be_roster->GetAppList(mySig,&appTeams); for (i=0; i< appTeams.CountItems(); i++){ myTeamID = (team_id)appTeams.ItemAt(i); BMessenger *bmsg = new BMessenger(mySig, myTeamID, &err); // send quit msg to all apps if ((err = bmsg->SendMessage(B_QUIT_REQUESTED)) != B_OK){ fprintf(stderr,"Failed to send quit request, SendMessage - %sn", strerror(err)); PostMessage(B_QUIT_REQUESTED); } delete bmsg; }
Coding Tips
If and when you decide to do some application coding of your own on Haiku, here are some tips.
When you use resources, QuickRes is a nice tool to add resources into your resource file. And remember that the application signature in the resource file must match the signature in App.h.
I like to use fprintf for debugging. It’s a little untraditional because it mixes console printing with a GUI. How does that work? It works pretty well if you use Paladin as your IDE, and if you start Paladin from a Haiku Terminal instance: bring up a Terminal from Tracker. After installing Paladin you can start it from Terminal by typing: /Haiku/apps/Paladin/Paladin. When you run your application, any standard IO output from fprintf will print to Terminal.
Using Application Instances
All very clever you say, but why would you write an application with multiple instances? There are several ways this can be useful. One reason is redundancy. When a process is critical and yet prone to failure it is useful to have 2 or more copies that monitor each other. If one instance dies it can either send a message it is quitting, or if it fails to respond, the other instances will know it has died and can take appropriate action. This is how monitors are implemented.
Applications can start with the same code but run completely different code by loading different library modules and invoking different functions. The Haiku kernel kit allows this with the load_add_on() method. In this way, the 4 instances of MessageDemo could start as the same program but perform completely different functions.
As Intel and AMD develop CPUs with 2, 4, 6, and 8 cores, developers have to come up with new ways to efficiently spread calculations over those cores. If calculations can be spread across multiple applications, the operating system scheduler will run the applications, and even the threads, across multiple system cores. Game coders are implementing IO, physics, AI, and graphics across separate modules for better game play. Haiku is friendly to coders who need to work with data and threads on multiple cores.
Summary
MessageDemo is a simple example to show the power and elegance of the Haiku API. With just a half dozen basic objects it lays out a foundation for applications that know about each other and can communicate effectively. Programming with Haiku is rich, rewarding, and easy. The objects used in MessDemo are just a few of the many powerful objects available to you in Haiku. Give Haiku a try and you will be amazed at how quickly you can write serious programs that use cool features. And when you have a cool application to share, upload it to Haikuware.com.
Haiku References
A Programmer’s Introduction to the Be Operating System.
Clear, straightforward and interesting of course, I really liked this article.
It’s nice to see this kind of content here in OSAlert besides the usual legal BS news
Yeah its great to see Haiku articles… and you’re right and I think the Legalese articles are a necessary evil .. they just make me want to hurl sometimes.
Well, I could ask who has the current ownership of all the BeOS IP and if there are any patents which could threaten project like Haiku.
But I won’t.
I don’t think I’ll be doing any BeOS/Haiku coding, but I think it is great to have such articles on OSAlert again.
It is interresting reading some of the ways Haiku works, how it has some of the elements similair to Mac OS X/systemd and current Linux desktop distributions.
Edited 2011-07-15 12:53 UTC
It’s all owned by a Japanese company, ACCESS, and for all intents and purposes it is mothballed and forgotten.
When YellowTab released Zeta, all they did was write letters.
Edited 2011-07-15 16:29 UTC
First, you obviously did ask the question. At least, you put the question in people’s minds.
Second, I tire of people raising “patent threat” questions about open platforms that mimic closed solutions. For example, I am a fan of Mono and it shows up endlessly in discussions about that platform.
A software API is not patentable (and generally not even copyrightable). These kinds of “non-asked” questions really confuse this issue. Implementing a specific API generally does not expose you to any more patent risk than writing a wholly original work with similar scope for a similar purpose.
To answer your question, Palm (now HP) owns the historical IP BeOS I believe. Does that mean that we need to worry about HP bringing legal action against Haiku. Maybe. Is this threat a specific one that raises the risk in developing Haiku. I do not think so.
The chance that Apple will sue instead is just as high or higher. I am not picking on Apple, they just seem to be the obvious party with the greatest potential competitive interest to a successful Haiku project. Patent trolls and dying vendors are even more likely. There is nothing special about the company holding the rights to BeOS.
Let’s use Mono as an example. I have been listening for years now to naysayers warning against using Mono because of the risk of Microsoft suing over patents. As a Mono proponent, I am at best too stupid or naive to understand the threat according to these people. Perhaps I am simply insane. Often, Java has been specifically mentioned as the safe and sane alternative. Is it really?
Well, Android is designed around the Java ecosystem and Oracle is now suing Google for patent violations. So, not so safe after all. But Oracle is at least the creator of Java (or has the creators rights) so perhaps some may see this as proof of why you need to worry about implementing other people’s specifications. Sadly, it is not so simple.
Microsoft has in fact attacked a half-dozen Android users (companies) and successfully negotiated licensing deals with them. Now they are going after Samsung, the largest Android handset vendor. Microsoft makes more money off Android than it does of Windows Phone 7. It is possible that Microsoft makes more money off of Android than any other software company. (I do not know at all but I wonder who is making more).
What engineering did Microsoft contribute to Android? None. What Microsoft specification, operating system, or development framework did the Android guys implement to attract all this attention? None.
Yet, you can use Mono to develop not only desktop and server apps for Linux and Mac. You can use Mono to develop mobile apps for iOS and Android. No lawsuits. In fact, Microsoft (a senior employee) has stated explicitly that Mono on Android is ok and that the Microsoft Community Promise was created to encourage exactly this kind of activity.
So which option turned out to be safer? It is hard to argue that Android would have attracted a greater number of lawsuits if they had based the platform on Mono instead.
This is not an anti-Java, anti-Android, or even (explicitly at least) pro-Mono comment. My point is actually that everybody is at risk from software patent claims. Patents are not like copyrights. It makes no difference at all who authored the software specification you are implementing. Your biggest threat is probably not the obvious vendor involved in the ecosystem but some other vendor that has no commitment to (or actively competes with) that ecosystem. Your biggest risk is being more successful with a patent holder that sees you as a competitor.
TL; DR
Who cares who owns the patents for BeOS. Haiku is neither safer nor more at risk because those patents exists. Haiku (and all software) is at risk because software patents exist in general.
Please stop raising the specter of patents for every project that strives for compatibility with something else.
As mentioned in the parent above… BeOS IP is owned by Access, a Japanese company.
Good article! Detailed enough to be useful, but short enough to not be intimidating.
I’ve been following the Haiku project since it was first proposed (as OpenBeOS), but I have to confess that I haven’t played with code on it for it for a long time. This article is just the reminder / kick in the pants I need to get the latest tools and code and get busy!
(I’m going to set it up in a VM, so I can also play with different numbers of VCPUs.)
For those not aware, Haikuware was hacked last week, so any of the article’s links which point to it will not work. For now, anyone going to the site will be greeted by a login window, but the site maintainer, Karl, is working on resolving the problem.
Hacking Sony is one thing but Hacking Haikuware – some people are just c**ts
Edited 2011-07-14 20:48 UTC
I know, right? Why don’t they hack Microsoft sites or Apple ones this time? For a change.
I just started my Programming in Haiku Screencast series a few days ago.
You can find the Screencast as flash stream and downloadable here: http://www.haiku-screencasts.blogspot.com
Cool stuff! Parts of that blog is in German, might I suggest you change it? Keep up the good work, screencasts are great
I fixed it. Thx for reporting
Nice article, but why pipe all the links through Google??
Yeah sorry about that – the article was handed to us in Google Docs, and after finally replacing all the links (BY HAND), I made a boo-boo and lost all my work. I didn’t feel like doing it all over again.
OT but couldn’t resist…Were you using your new iPad when boo-boo happened
Nice article, well written and thought out! I’ve been looking for a bit of time to start coding on Haiku, and maybe this is the little push I needed to get cracking! More of this please
Good, pure technical read. Perhaps a bit too involved for a typical beginner (application rosters, media files), but then again – it is nice to see some of the more advanced stuff in an introductory article.
If I had to name one Haiku API feature as its distinct forte, I’d say Messaging. It is simple yet so powerful. I often miss the BeOS messaging design in other programming frameworks.
First, let me say that I like the article and Haiku seems interesting. The question I have however, is why would I, as a developer, spend time developing for Haiku?
I don’t know the os, and I also never ran BeOS. From the website, it’s not really clear what kind of hardware Haiku supports (well, except for the fact that it should run on x86 systems), and whether it is usable for day-to-day use. Is Haiku at this stage more of an experimental os that people run in a virtual machine? Or is it usable as a primary os?
It’s also not really clear which programming languages are available on Haiku, besides C and C++.
Well, I’d like to develop for Haiku, purely to support their efforts. There are so many small applications on other platforms which are taken for granted that Haiku simply doesn’t have, or has an old version of. And you get that warm, fuzzy feeling of writing software for a small community who would really appreciate it – a feeling that isn’t available in the Windows shareware world for example.
As for the OS itself, it’s still in Alpha so no, it’s not really set for daily use yet. I run it natively on my machine, but I had the luxury of a spare PC lying around to use for these things. There’s always a risk that it can mess up, or not be fully compatible with your setup, so a virtual machine is probably the way to go for now… C and C++ are the main languages, and Python is there too, though I haven’t heard much about the GUI toolkit support (Qt etc.). Not sure what else is available, but I’m sure more will show up.
Qt port is available on Haiku, not sure about the development tools, though. http://qt-haiku.ru/
C++ is currently the language of choice for writing GUI apps for Haiku at the moment, but there are other languages available for other uses, including Lua, Pascal, Ruby, Python, and Perl.
There is a GSOC project which is working on bringing GUI bindings to Python and a few other languages. <shameless plug>I have a similar project with similar goals, but a totally different implementation which should make it really easy to write bindings and make improvements on the API at the same time. The Lua bindings are 75%-90% complete.</shameless plug>
If you are new to programming AND Haiku I highly recommend this tutorial series:
http://www.haiku-os.org/blog/darkwyrm/2010-09-08_new_series_lessons…
It is a nice intro to programming, using basic Haiku applications as examples. You can get the whole series as a single e-book, which is very convenient.
Last I checked they had imported most of the Linux and BSD hardware driver stacks, though there was a bounty out on orting the Gallium3D video drivers.
So, yes a VM would be your best bet to run it, but it should b able to boot on anything that boots Linux, key word there being should…
As for why you would want to run it or write anything for it:
1.) As yet another couriosity.
2.) Pet project maybe?
Edited 2011-07-16 03:30 UTC
Ah… ok… that about the drivers was not really clear. In any case, I will check it out sometime. It does seem interesting!
I probably could use Haiku as a Main OS. To be honest, most of the apps that still don’t exist, have online versions (Office -> Google Docs; MSN -> meebo, etc..).
Having said that, I’ve run it sucessfully on hardware ranging from P3 1Ghz (actually they were Celerons but..) with a gig of ram (a bit overkill I know), to a Q6600 with 3GB and GTX260 with onboard Realtek sound and network with no issues at all (apart from the non-existing 3D acceleration).
Due to the ported stacks from BSD et al… I think that Haiku hardware support is actually preety good if you don’t own any “exquisite” hardware.
Tonight I’m gonna actually try and have a go at running it on my MacBook Pro mid-2010.
it did not age too badly for a 20 years old API
Its aged, and it was aged 10 years ago. Still using “const char *” for all titles for example. C++ evolved, the BeAPI hasn’t.
I don’t remember C++ introducing a new basic type for strings. Are you confusing with sdt::string by any luck – which is not a C++ stuff but a STL one.
Indeed.
You guys did a good job then.
This is all your fault if this API is still alive – whatever demographic numbers.
good to see this post. was/is a big fan of the API. it’s clean consistsnt and easy to learn.
I do alot of programming on other systems these day and find myself wondering why even some of the most modern ones lack some of the concepts put forward by beos’s subsystem layout and APIs.
Hey, great article. Easy to read and educational. Thanks.
About Haiku OS, you said the project’s been ongoing for 10 years and is only in its 3rd alpha release? Yikes, in Internet Time, this means it will be several generations before they come out with a first production release. I understand how it’s a labor of love for those involved but for the rest of us, we’d feel more comfortable about using Haiku if they’d put a standard release out there.