Issue 1-25, May 29, 1996

Be Engineering Insights: We Deliver

By Peter Potrebic

In a previous column (Issue 1-13), I wrote about the various ways to send data on the BeBox. In another column (Issue 1-4), I talked about the dangers of race conditions and deadlocks, problems inherent in a multithreaded OS. Now I'd like to bring these two topics together and talk about the differences between posting messages through BLooper's PostMessage(), and sending messages through BMessenger's SendMessage().

Posting a message is simple. Given a pointer to a BLooper object, you simply invoke PostMessage() upon that object, passing a BMessage object as an argument. A subtlety here is that this implies that you're holding onto a pointer: Most programmers remember learning about the dangers of pointers. Once you have a pointer to an object, you're tempted to do other things with that pointer, like dereference it to access a data member, or call some virtual function. Unless the code properly locks and unlocks the object, either of these actions can lead to an immediate, abrupt, and unpleasant suspension of further computation! (Check out the "Be Newsletter," Issue 1-4, for more details.)

An alternative is to use BMessenger's SendMessage() function. Prior to DR7, BMessenger objects could only refer to BApplication objects. In DR7, a BMessenger can refer to any BHandler (in other words, any object that can receive a message). This is an obvious boon to interapplication communication and, interestingly enough, it also provides a new way to do intra-application messaging. Instead of saving a pointer to a BHandler, you can create a BMessenger that represents that object. Using SendMessage() to communicate with a BHandler is completely safe. Plus, there are no pointers involved so the temptations are minimized.

Now let's consider "safe locking": The safe locking of pointers is pretty safe, but it does contain a hole. Suppose you have a pointer to a BWindow and you call Lock(). Lock() will return FALSE if the object no longer exists. Now suppose just before calling Lock() the BWindow was destroyed and a new BWindow was created and, furthermore, suppose the new object is allocated at the same memory location as the old object. In this case Lock() will return TRUE. The new window will be locked, even though, in the semantics of the code, the old window was the target of the Lock() call. What happens after this is anyone's guess.

With BMessengers this can't happen. A BMessenger to an object is unique for the life of the application. Memory addresses or pointers, on the other hand, can be recycled. This makes using BMessengers and avoiding pointers the safest way to go. The style of coding that I'm suggesting might look something like this:

TMyApp::TMyApp()
{
   TMyWindow *w = new TMyWindow(...);

   // Instead of saving the window pointer,
   // you save a messenger to the window:
   fWindowM = BMessenger(w);

   TMainView *main_view = new TMainView(...);

   // Similarly for the view:
   fMainViewM = BMessenger(main_view);

   w->AddChild(main_view);

   ...
}

In the example the application object uses the BMessengers to communicate with the BWindow and BView. If one of these objects (the BWindow or BView) is deleted, the corresponding BMessenger will report an error the next time it's used. In this way the holder of the messenger is safely informed of its cohort's demise.

Another benefit of BMessengers is that they have built-in support for replies. If you post a message to another object in your application, there's no way that you can reply to that post. However, with every SendMessage comes an automatic return address. So for every message that's sent, the receiver can do a SendReply(). This can be a useful tool.

The downside to BMessengers is that they're more expensive than pointers: A pointer is only 4 bytes, a BMessenger is 16. Also, PostMessage() is currently faster than SendMessage(). And of course, sending a message is significantly more expensive than simply accessing some data or calling a function. If some set of objects is tightly coupled, then using BMessengers might not be the right solution given the performance penalty.

Here's another programming tip that makes use of the messaging system. We've received some feedback indicating that our framework forces frequent subclassing in order to extend functionality. I'm not denying that the framework is so oriented, but there are some nice ways to avoid this problem. One example is when one window (let's call it the "document window") wants to open a dialog box asking the user for some input. Let's say this dialog has two views: An input text field and a "Do It" button.

At first glance it seems like you have to subclass BWindow to process the message posted by the "Do It" button. However, there's another way that doesn't require any subclassing. The document window creates the dialog window and adds the two views. The document then calls BControl::SetTarget() on the button, making itself the target of the button. Even though the button lives in the dialog box, the message it sends when clicked will go to the document window. Finally the dialog is displayed and the document window goes on its merry way. Now, when the user clicks the "Do It" button a message is sent to the document window. From this message the document can get the button, dialog, and any other information in the dialog. So once it extracts all necessary information, it tells the dialog to close. End of story. You get a nice little dialog without any subclassing (except, of course, for the document window itself, which must be a subclass of BWindow).

The SetTarget() functions in BControl, BMenuItem, and BListView are very useful—give them a try.


Be Developer Profile: Infant Software

From the day he first read about the BeBox, Sean Allen, partner and programmer at Infant Software, was hooked. “I wrote to Be and asked if the $1,500 price tag was a typo—they said no. That price, that power, a built-in database, multithreaded, preemptive multitasking: Geek love!” Sean thought it was rather fitting that his BeBox arrived on Valentine's Day.

With the right marketing, the BeBox can explode. I expect the machine to grab large chunks of market share over the next few years. It will gobble up the NeXT and Amiga camps, video and MIDI markets look ripe too, and it would make a killer DTP machine. Once people experience a BeBox and see the price, converts are easy.

Not only does Sean see market potential for the BeBox, Infant Software, a four-person company that develops custom CGIs (Common Gateway Interfaces), databases, and free/shareware, is betting its future on Be: “We've decided to forgo our current platforms (Macintosh and UNIX) and be a Be-only company. We want to carve out our ground now and be there with one of the tractor application when the BeBox explodes.

Sean and his partners are working on a modular suite of Web tools, which use the Be OS™ database to share information. Modules include a web server, a visitor tracker, an API for CGI-type work, and game modules. They plan to publish their messaging API so anyone can write a module that will work with their tools.

We believe everybody has the right to the basic tools to make their computers useful, so we'll make our core tools available for free. We'll only charge for add-ons, like the visitor tracker.” They anticipate releasing the first tools in the first quarter of 1997, followed by additional modules, such as a software metering API, various distributed network applications (including games), and "agent" software.

Unlike other platforms he's developed for, Sean says, “I feel like I really have a chance to put my stamp on the Be OS—to help shape it, to help it grow. Developers really matter to Be, and that's a refreshing change.

What's more, the BeBox is fun to program: The Be OS is 100 times easier to program than the Mac OS, 500 times easier than Windows, and 75 times easier than UNIX. That means shorter development times, better products, fewer bugs, and more time to dream, design, and build incredible software.

I am, quite simply, in love with this machine.

For more information on Infant Software, send e-mail to runt@inch.com.


Working at Be

By Jean-Louis Gassée

We get many inquiries concerning employment opportunities at Be. With these inquiries come questions regarding the company's style and philosophy in such matters: What's it like working at a start-up such as Be? What sort of individuals are we looking for? We'll skip the usual meaningless platitudes: Honest, hard-working, creative, intelligent... (Of course we admire these qualities—but when was the last time you saw a resume that extolled the candidate's exemplary uncreativeness, sloth, and dishonesty?)

Let's proceed by comparison, then. In many large companies, the "product," at the work-a-day level, is broken down into "projects." Individual projects get sliced and diced into manageable components, and the components are parceled out to individuals according to their specialized training and experience. To coordinate the project components, you need project management; a premium is placed on management's ability to orchestrate, adjudicate, and focus the blindered energy that emanates from a line of wall-facing cubicles. A significant amount of time, money, and emotion are spent not in crafting the project itself, but in crafting the crafting of the project: In the careful placement of the walls between the compartments, and the minutiae of passing data over these walls. And this is just to mention the lowest level of management.

At Be, we hire people, not projects. Of course, we have certain tasks that we want to accomplish, and we have, at times, targeted prospective employees because of very specific talents. But, in general, we want individuals whose personalities and training make them comfortable with an environment where they're expected to grasp the whole concept, find a niche (or a canyon) that needs filling, and then start digging. We want to create an environment where the biggest chunk of any particular problem (be it engineering, marketing, manufacturing, finance...) resides inside a single human head. No turf wars, no miscommunication, and no layers of management.

This is an approach that only a small company can take—and if Be is going to win, we must take this approach in order to turn our size to our advantage. To the other guys, we look like ants; but from our perspective, they look like lumbering, graceless dinosaurs.

Another important trait that we expect in our employees is that they have a clear sense of the business purpose of their own actions. It's not enough that they think that they're providing a valuable service, or, worse, that they simply take marketing's word for it—they must know why it's important. In most cases, they should even know the names of the developers that their work will benefit most. At Be, "because marketing asked for it" is simply not an acceptable answer.

We want engineers to act upon their own estimation of what their clients will want, like, and pay for. We expect a similar understanding of the business across the entire organization. Now, what kind of Human Resources organization do we have to ensure this shared awareness of and commitment to the common purpose? None.

Most of us have observed the damage caused by addictive HR organizations. In the beginning, they relieve stress. Soon, they insinuate themselves into every aspect of corporate life and withdrawal pain becomes impossible to bear. Not unlike some welfare programs, HR becomes an end unto itself, a means of existence for a group of individuals whose sustenance depends upon their clients' problems. Decisions are laden with their intervention. Straight- forward processes are gummed up with their arbitration.

In a way, HR is a protection racket. A process must be put in place, a study must be made, a task force must be set up; thus management is protected and absolved of political responsibility, and HR gains power.

One of the benefits we offer at Be is that there's no HR and there won't be any. Personnel, yes. Forms, benefits, insurance, 401K—these are all healthy and regular paperwork movements. If we ever need HR work, we'll bring consultants to help. And then they'll leave. Just as we want our employees to own their work, so do we want an unobfuscated (and minimal) management to be fully responsible for its actions.

As for turnover: On a small sample size such as ours (population 30) statistics don't tell much. We've consistently lost two or three people every year. Our goal is to detect an ill-fit between the individual and the mission as early as possible. One of the benefits of early detection is a more amiable parting of the ways before frustration and bitterness set in. So far, it seems to have worked: One ex-engineer even treated the entire company to (good) pizza to help celebrate the BeBox intro. Another helped us recruit a new employee at a crucial juncture. But enough syrup; the bottom line is that we can only succeed if we continue to attract and hire a (small) number of mature, broad-minded, self-reliant individuals.

To be an efficient guerilla-type company, we need the kind of professionals who seek and will contribute to maintain such an environment. You can come from a large company, or be straight out of college: It doesn't really matter as long as you fit the environment you're in charge of creating.

Creative Commons License
Legal Notice
This work is licensed under a Creative Commons Attribution-Non commercial-No Derivative Works 3.0 License.