| Version | 1.1.0 | |
| Last-modified | 25. June 1998 | |
| URL | <http://www.begeek.com/ArticleDisplay.servlet?ArticleID=157> | |
| Author | Ingmar Krusch <clueless@begeek.com> (feel free to mail any comments, suggestions, corrections, Q&As etc. to this address). | |
| Copyright | The entire BeDevTalk FAQ document is Copyright © 1997 and 1998 Ingmar Krusch <clueless@begeek.com>. All rights reserved. All wrongs also. Copying is permitted only under designated situations [1.3]. For details, see section [1]. | |
| No warranty | This work is provided on an as is basis. The author provides no warranty whatsoever, either express or implied, regarding the work, including warranties with respect to its merchantability or fitness for any particular purpose. |
BApplication instance?strtok() not thread safe?BMessages reference counted?BMessages?<iostream.h>, won't build. Why?<iostream>s, won't compile. Why?mmap()?fork()/exec() inheriting open file descriptors?popen()?MouseUp() isn't ever called. Why?FindWindow()?BMessage to a particular BWindow rather than to the BApplication it belongs to?BMessenger for every open BWindow in the Tracker?BFilePanel to select directories?int64 (long long) using printf()?Ingmar Krusch <clueless@begeek.com>
The BeDevTalk FAQ is always improving. Your input is most welcome. Send your comments, suggestions, corrections, Q&As etc. to <clueless@begeek.com>.
The entire BeDevTalk FAQ document is Copyright © 1997 and 1998 Ingmar Krusch <clueless@begeek.com>. All rights reserved. All wrongs also. Copying is permitted only under designated situations [1.3].
Portions of the Be Book and Be Developer Guide quoted herein are Copyright © 1998 by Be, Incorporated, and are used by permission.
If all you want to do is quote a small portion of the BeDevTalk FAQ (such as one or two FAQs) in a larger document or an email, simply attribute the quoted portion with something vaguely similar to, "From the BeDevTalk FAQ, <http://www.begeek.com/ArticleDisplay.servlet?ArticleID=157>:".
If you want to make a copy of large portions and/or the entire BeDevTalk FAQ document for your own personal use, you may do so without restriction (provided, of course, that you do not redistribute the document to others, or allow others to copy the document).
If you want to redistribute large portions and/or the entire BeDevTalk FAQ document to others, whether or not for commercial use, you must get permission from the author first (and that permission is normally granted; note however that it is often easier for you to simply tell your recipients about the download option [2.2]). Nevertheless, this FAQ was produced for free redistribution, so you must not charge any kind of fee if you are allowed to redistribute this FAQ. In any event, you must retain and conspicuously display all copyright notices on all copies of the documents you copy, and you must include the Author [1.1], Copyright Notice [1.2], No Warranty [1.4], and Copying Permissions [1.3] items, and display these items conspicuously.
If you want more and/or different privileges than are outlined here, please contact me, <clueless@begeek.com>. I'm a very reasonable guy...
This work is provided on an as is basis. The author provides no warranty whatsoever, either express or implied, regarding the work, including warranties with respect to its merchantability or fitness for any particular purpose.
Restriction 1: You must still abide by the Copyright Notice [1.2] and Copying Permissions [1.3]. In particular, you must not redistribute the BeDevTalk FAQ to others without permission from the author [1.1]. If you want to redistribute the BeDevTalk FAQ to someone else, the easiest way is to tell them about this download feature [2.2], and let them get their own copy.
Restriction 2: The BeDevTalk FAQ uses long filenames. If your machine can't handle long filenames (e.g., if it is DOS and/or Windows 3.x), you may run into trouble browsing the unpacked files. BeOS, MacOS, UNIX, Windows NT/95, Amiga etc. all handle long filenames correctly.
subscribe BeDevTalk
You can also use the form on the Be web site to send the correct subscribe message:
<http://www.be.com/aboutbe/mailinglists.html>
You can only send messages to the list if you are a subscriber. You must send your messages from the account with which you subscribed to the list.
unsubscribe BeDevTalk
You can also use the form on the Be web site to send the correct unsubscribe message:
<http://www.be.com/aboutbe/mailinglists.html>
You can only unsubscribe from the list using the account with which you subscribed to the list. The list server is very picky about From: addresses, and if your apparent address changes, due to changes on your network or mail server, you may be unable to unsubscribe. If this happens, send mail to <listmaster@be.com> and request a manual unsubscription.
development-related topics would be things like:
- This doesn't work like the BeBook says!
- Bugs in the BeOS or Be Kits that affect development [4.1]
- This code gives me trouble!
- API discussions and discussion of design considerations
- Application design
- How should I implement something?
Off-topic and/or inappropriate posts would be things like:
- How do I set up this program?
- How do I set up this Hardware Device?
- HELP - My Computer won't boot!
- You/this suck(s)/rule(s)
- Lisp is better than C++ is better than AREXX is better than ...
- Is the listserver down? Am I still subscibed?
If you suspect that the listserver is down or you got unsubscribed from the list somehow, do not post test messages to the list. Instead, try subscribing again, this will yield exactly the same information to you as a test message without annoying other list memebers.
Every member of the list will benefit from keeping the signal-to-noise ratio high. Please do not answer a question that does not conform to the List Charter [3.1] or Netiquette [3.2]. Instead politely but firmly point the questioner to an appropriate place for these issues (please send mail directly to the person and CC <listmaster@be.com>; do not post such comments to the list). These may include:
Please do not answer a question that is already in the FAQ. Instead politely but firmly point the questioner to the URL of an appropriate FAQ (please send mail directly to the person, do not post such comments to the list). These may include:
- Bad Subject: "HELP"
- Bad Subject: "Problem"
- Bad Subject: "(none)"
- Bad Subject: "Re: BeDevTalk Digest for 11/6/97"
- Good Subject: "Clearing Messages from the message queue"
- Good Subject: "BLooper loses Messages"
- Good Subject: "Should this be a shared library or a server?"
"Subject: Who owns BMessages (was Re: Clearing Messages from the message queue)"
While talking about bugs that affect development and possible workarounds on BeDevTalk is fine, this will most likely not result in a bugfix for the OS, no matter who is involed in the discussion:
Submiting each and every Bug you find in the BeOS and the BeBook at Be's Webpage via their Bug Report Form at <http://www.be.com/developers/bugform.html> earns good Karma!
Yes.
You can write a substantial app with the limited linker.
The CodeWarrior that comes with BeOS has a limited linker--it can only link projects smaller than 64k of code [6.5], the amount of data in not limited. The quality of the compiler you buy is the same as the one that comes with the OS. If your commercial-quality app is bigger than that, you will need to get the full version from Be (yes, the CodeWarrior package for BeOS is distributed by Be, check their website).
Another benefit to owning the full version is, of course, that you can use any updates that come along (the updates they post on their Web site are generally only for the commercial version of their software, and not the limited one on the BeOS CDs).
If you for some reasons cannot afford the full CW, you are out of luck for now. Be's official answer can be found at <http://www.be.com/support/qandas/faqs/faq-0020.html>.
If the only thing in your resource file is what shows up in FileTypes--the version info, app sig, and icon, then FileTypes works fine. For more elaborate resource files, you may find Interface Elements or AppSketcher meets your needs, look for those two applications on your BeOS CD, but there are probably newer versions available. Check BeWare. Although setting the signature is best done in the FileTypes application or the FileType Tracker add-on.
There is a Java compiler, AWT implementation, VM with JIT, and development tools available from Metrowerks. Development tools come with a license for you to freely bundle the VM and JIT with the application you develop in Java. Check your CodeWarrior license for details. Thus, you can develop as much Java as you want and ship it to your customers.
You don't.
Saving preferences as resources in the application has several drawbacks.
The Mac does not (despite common believe) save settings as resources in the application in any application that was written the last 10 years. The reason for this is that applications may sit on a CD-ROM, or they may be on a read-only file server, or they may be on a file server where more than one person can start it at the same time, or the user may have anti-virus software that prevents application file modification, or any imaginable other situation that breaks trying to write to your own application file.
Most of these reasons also hold true for the argument that the settings file should be in the same folder as the application: There simply is no guarantee that it is writable.
There are system-defined settings folders (check out /boot/develop/headers/be/storage/FindDirectory.h); use them. You may also want to check out the preference library libprefs.so on BeWare.
Be resources can't be stored together with actual data. You can store either resources or your own data in a data file--the only exception being an application/shared library/add-on, which is a special-case of the resource file format that allows both code and resources in the same file.
The Be Way(tm) is to store window positions and other such document-dependent things as attributes for the file (which follow the file around wherever it gets moved, copied or duplicated). This already works great for e.g. the Tracker and BeIDE. It should be mentioned that if you move files with attributes across a foreign file system that does not support attributes (HFS, NFS, FAT, ...), this information is lost. All attributes unknown to an application should be copied unmodified. Similarly, every application has to be prepared to deal with inconsistent attributes vs. the file content.
Put this in your /boot/home/.profile file:
function hgrep
{
find /boot/develop/headers -name \
*.h | xargs egrep -n "$@" /dev/null
}
Now looking for any function definition is easy:
$ hgrep spawn_thread
/boot/develop/headers/be/kernel/OS.h:230: extern thread_id spawn_thread (
$
This hgrep function searches the headers directly, not the current working directory. You use it much like egrep and this function lets you pass egrep arguments directly to hgrep.
The BeOS API is currently expressed in C++, so questions in this area are per definition BeOS related and as such a logical topic for BeDevTalk. However, before subscribers rely on the list to answer basic questions about C++, please consider that there are good C++ resources on the net as well as in printed form where people should find answers to most basic language questions.
List subscribers can't possibly teach each other C++, the list can only serve the purpose of a discussion forum. As such, a basic understanding on how to program/develop is required before posting C++ related questions to the list. Nevertheless it should be stressed that there is no such thing as a dumb question, only too basic and therefore not appropriate questions (for this list).
As for net-based resources, there are the newsgroups
and many more, refer to your local news server. It is not uncommon for Stroustrup, Koenig, and other people involved with the design and evolution of C++ to answer questions on those newsgroups.
In addition, there are several C++ FAQs available on the net, try out:
Worthwhile for the BeOS programmer are also the following multithreading related FAQs:
There are also several introductions to the STL and the ANSI C++ Standard Library:
Please keep in mind that it used to be called the STL, and it used to be developed by Stepanov. It is now made part of the ANSI C++ Standard Library, and there were some subtle changes made in that process. Any book using the old STL, or making references to the STL, not to the ANSI Standard C++ Library, could (possibly) lead you astray in several places. Getting the most up-to-date book on the ANSI C++ Standard Library is recommended.
Also note that the Metrowerks implementation (the one you have available with the BeOS) is not based on the HP code.
Furthermore, several books have been recommended on BeDevTalk in regard to C++ and development in general (in no particular order):
Name Author Press Comments Effective C++ and More Effective C++ Scott Meyers Addison-Wesley Considered as a must have, both are very easy for the beginning C++ programmer to dip into, while still being useful for the more experienced developer. The C++ Programming Language, 3rd Edition Bjarne Stroustrup ??? The third edition is possibly the best single book to get as it is both comprehensive and current. It is one of the very few books to deal with the ANSI C++ Standard Library, rather than the old STL. Do not expect a reference, this is more of a learning guide. It does try to be complete, so don't expect a quick read! Industrial Strength C++ Mats Henricson, et al Prentice-Hall This book expands the public domain Ellemtel C++ coding standard. The presented guidelines define a C++ coding standard that should be valid and usable for almost all programmers. Taligent's Guide to Designing Programs: Well-Mannered Object-Oriented Design in C++ Inc. Taligent Inc. Taligent A quick overview of Object-oriented program design, with special regard for operating-system development. A provocative summary of good OOP techniques. C++ Primer, 3rd Edition Stanley B. Lippman Addison-Wesley Introductory book on C++ as a learning tool and as a reference. Writing Solid Code Steve Maguire Microsoft Press For professional intermediates to advanced C programmers who develop software, here is a focused and practical book based on writing bug-free programs in C. Includes practical solutions to detect mistakes before they become a costly problem. Advanced C++ Programming Styles and Idioms James O. Coplien Addison-Wesley Coplien shows how to become an expert C++ programmer by learning the idioms of the language. His approach is organized around the abstractions that C++ supports. He shows how these abstractions can be combined to use the language effectively. Code Complete Steve McConnell Microsoft Press Presents an expert look at the process of commercial software development. Lots of example code, insights on managing technical yet creative people, and examines each milestone in software development in detail. Large-Scale C++ Software Design John S. Lakos Addison-Wesley Shows how to decompose a large program into a number of smaller, more easily manageable components. A single 12,000-line code example runs throughout the book which shows the reader how to build a complex project which the professional can use later in actual work. STL Tutorial and Reference Guide Musser and Saini Addison-Wesley This is a must-have reference to the STL portion of the C++ Standard Library. Atul Saini, one of the authors, is the principal behind Modena, who wrote the CodeWarrior STL. Design Patterns Gamma, Helm, Johnson, and Vlissides Addison-Wesley A review of recurring constructs in software development, but put it into a larger, connected framework. Very good. Operating System Concepts, 4th Edition A. Silberschatz, Peter Baer Galvin Addison-Wesley Clear coverage of the fundamental concepts which are the foundation of operating systems. The book has been revised to decrease coverage of older ideas, and expand discussion of new, common operating systems. Modern Operating Systems, 2nd Edition A. S. Tanenbaum Hanser/Prentice-Hall Provides a balanced coverage between centralized and distributed operating systems. Part I covers processes, memory management, file systems, I/O systems, and deadlocks in single operating system environments. Part II covers communication, synchronization process execution, and file systems in a distributed operating system environment. Includes case studies on UNIX, MACH, AMOEBA, and DOS operating systems. UNIX Network Programming W. Richard Stevens Prentice-Hall A classic, all-around book covering a wide range of network programming issues and parts are still very applicable to the BeOS BSD sockets interface. TCP/IP Illustrated, vols. 1-3 W. Richard Stevens Prentice-Hall A series on networking which covers TCP/IP in a much more in-depth fashion than Unix Network Programming. For the advanced networking programmer. POSIX Programmer's Guide: Writing Portable Unix Programs With the Posix.1 Standard Donald Lewine O'Reilly & Associates Intended as an explanation of the POSIX standard and as a reference for the POSIX.1 programming library, this book helps writing more portable programs. This guide is especially helpful when writing programs that must run on multiple UNIX platforms. UNIX Systems Programming for SVR4 David A. Curry O'Reilly & Associates Presenting the nitty gritty details on how UNIX interacts with applications, this book offers a thorough explanation of all UNIX system calls and library routines related to systems programming, working with I/O, files and directories, processing multiple input streams, file and record locking, and memory-mapped files. OpenGL Programming Guide OpenGL ARB, Woo, Neider & Davis Addison-Wesley This book explains how to create graphics programs using OpenGL, Release 1. It presents the overall architecture of OpenGL and discusses in detail every function included in the specification. Numerous programming examples in C show how to use OpenGL functions. OpenGL Reference Guide, 2nd Edition OpenGL ARB Addison-Wesley Explaining how graphics programs using Release 1.1, this book presents the overall structure of OpenGL and discusses in detail every OpenGL feature including the new features introduced in Release 1.1. Numerous programming examples in C show how to use OpenGL functions. Also includes 16 pages of full-color examples. About Face: The Essentials of User Interface Design Alan Cooper IDG Books Worldwide Presents a methodology of user-interfaces. Helps designing user-interfaces with the user's goals in mind, arguably the whole point of UI design. This book does not focus on code; instead it discusses highly technical topics in clear English (or French or German, whatever your copy is written in :-).
The BeOS provides a defined format and classes to deal with versioning, which is the same format as for BApplications. The version info is stored in an APPV resource of the library or application (so it does not get lost in FTP, and gets pulled into an attribute). See the BAppMimeInfo class and the serversion command-line tool for additional information.
BApplication instance?
You have a complete connection to the app_server from the time of construction of your BApplication until the object is destructed. This includes before, during and after a BApplication::Run() execution:
int main()
{
BApplication app("application/x-what-ever");
/*
your code goes here
*/
return B_OK;
}
You will need this connection in order to use most parts of the Be Kits, e.g. BBitmap, BView, BWindow, ... That's right, you won't be able to use those classes unless you have this connection.
You should set it in a resource file included in your project, and as the constructor to BApplication. Those both have to match and you have to set it in both places. The FileTypes program can generate a resource file that tells the Tracker what your mimetype is (and the Tracker then caches it into an attribute). The run-time BApplication constructor argument informs the run-time system of the applications mimetype. This way the information can be rebuild if the Tracker generated attribute gets lost, for instance.
Some related URLs:
You probably have shared data (even read-only) that your threads are working with and a 603 PPC based computer.
The problem is that the 603 PPC chip only implements an MEI cache protocol. This means that data in the 603 PPC's cache is in one of three states: (M)odified, (E)xclusive, or (I)nvalid. Notice that there is no state which says that cache data could be (S)hared between this processor and another. This is the nature of the cache thrashing which occurs and is also one of the reasons that the 603 PPC is not recommended for use in MP systems but the 604 PPC is (the 604 PPC implements a MESI cache protocol).
To illustrate the point, consider two threads, each running on a different processor, which are merely reading the same shared data. Processor one (P1) reads the data, storing the result in its cache and marking that cache line as Exclusive, data is in P1's cache only. Processor two (P2) then reads the data, storing the result in its cache, with the same effect on P2's cache. However, this second read is detected by P1, causing P1 to change the state of the cache line in its cache. Thus, P1's cache line becomes Invalid (in a 604 PPC, it would become Shared). Therefore, when P1 again reads the global data, it must refetch it from main memory. This invalidates P2's cache line and the whole cycle begins again.
Another problem may be if many threads are doing memory allocations simultaneously via new(), then every new() needs to "lock the heap" because the heap is a global structure; so all the new()'s need to be serialized. This of course drops performance if one would call new() in a tight loop from several threads, say to multithread a computation. This is more noticeable on slower machines than on fast ones. The current workaround: Don't do that. Move the new() and delete() calls to a less frequently called spot (see Bug report 970722-075741).
Because the current working directory (cwd) is set to where the application is when running in the debugger, set to who-knows-what when run from the Tracker and to where you are when run from the shell.
If you always want the cwd to be the same location, e.g. where the application lives, invoke this function on startup:
#include <app/Roster.h>
#include <storage/Path.h>
#include <storage/Entry.h>
#include <posix/unistd.h>
void SetCurrentDirectory()
{
app_info info;
BPath path;
be_app->GetAppInfo(&info);
BEntry entry(&info.ref);
entry.GetPath(&path);
path.GetParent(&path);
chdir(path.Path());
}
Error checking is left as an Exercise For Reader(tm).
strtok() not thread safe?As a rule of thumb, most ANSI C or POSIX 1003.1 functions must be thread safe (for POSIX 1003.1 compliance), although there are some exceptions:
- asctime()
- ctime()
- getgrgid()
- getgrnam()
- getlogin()
- getpwnam()
- getpwuid()
- gmtime()
- localtime()
- rand()
- readdir()
- strtok()
- ttyname()
All of these functions have _r versions (e.g. asctime_r()) that are guaranteed to be thread-safe. Note that these may not all be available under BeOS, requiring a manual wrapper of semaphores around these function calls in order to make them thread-safe.
This should not be a problem when porting single-threaded code to the BeOS, but may be an issue when writing new, multi-threaded code.
BMessages reference counted?BMessages?
There is no reference counting in BMessages. BMessages are copied on SendMessage()/PostMessage(). In order to save overhead for passing large data there are several options:
In either case, in order to know when to release the memory/area, it is nescessary to implement a custom reference counting scheme. There are other options like writing data to a port/pipe following some self designed protocol.
- Within the same address space just pass a pointer to data.
- Across address spaces set up a shared area and pass references to that shared area.
Related info:
- Calling
PostMessage()on any message does not transfer ownership of theBMessageobject to the system. So if you own the message that you posted you are responsible for its proper destruction.- The
BMessageyou get inMessageReceived()is owned by the system, therefore it is forbidden to delete it (you did not construct it so do not destruct).- If you repost/resend a
BMessagethat you received, any replies to that resend will still go back to the orginal sender:A sends to B, B resends to C, C sends a reply (it will go to A)
First, this has nothing to do with the BeOS being backwards-compatible. A later release (LR) will run all existing software for all previous releases (PR).
The PR might not run LR software, however, because the LR adds new features that are not in the PR. A PR isn't expected to run LR software.
A problem arises if new features are implemented in a LR through new virtual member functions of existing classes (using the virtual void reservedXXX() methods, or whatever they're called; Be engineers tend to be very creative, read the headers for a laugh or two), thus an application compiled under a LR will not run on a PR, even if you do not use them! This only happens if you use (or derive from) the class(es) that get new virtual members. Instantiating a class with virtual members means you are using all of those members, even if you, yourself, are not calling them directly. So, in a sense, you are using the new functions, just not realizing it. After all, the internals of the object may call those virtual functions behind your back.
If you really do not use them you can simply compile with the older headers and libraries from the appropriate BeOS CD, and thus link your application without pulling in those new symbols:
- Copy headers and libraries from some former version of the BeOS into a folder on your hard disk.
- Set the Access Paths:
- If you are using a CodeWarrior project, set the Access Paths in BeIDE to point to these older headers/libraries, rather than the current versions that would normally be used for the release you are executing on.
- If you use makefiles and the command-line tools, set the BEINCLUDES and BELIBRARIES environment variables to point to these older headers/libraries, rather than the current version.
- Build your application.
One important thing you have to keep in mind are RP bugs whichwere fixed in a LR, but your app's work arounds do not take this into consideration. The only way to deal with this is to develop under the PR and test it there a lot. If that is too much effort, then develop under the LR and test under the PR, a whole lot. Remember that (hopefully) many bugs were fixed since the PR. You can write code under a LR that works fine and as explained in the BeBook but which will not work correctly under a PR.
Be no longer supports using PreviewRelease 1 or earlier releases of the BeOS, so developing for PreviewRelease 2 or later, and suggesting your customers use PreviewRelease 2 or later, is reasonable. PreviewRelease 2 is freely available as an internet download, so there is no reason for customers to be using an earlier release.
Generating Be executables on the Mac with the Metrowerks tools is just a matter of copying over the appropriate headers and libraries and getting your access paths correct. The Metrowerks PPC tools on the Mac generate the same executable format as the Be tools. BTW, with CodeWarrior for Windows NT you can do the same thing.
Be aware that these are unsupported uses of the tools, but should work.
Either recode the if-statement like this:
if (someVariable = SomeFunction()) {
/* Do Stuff, because result was not false */
}
to something like:
if ((someVariable = SomeFunction()) != false) {
/* Do Stuff, because result was not false */
}
or you use a pragma:
#pragma warn_possunwant off
if (someVariable = SomeFunction()) {
/* Do Stuff, because result was not false */
}
#pragma warn_possunwant reset
For chronic command-line people who never want the warning, this will work, too:
$ mwcc -pragma "warn_possunwant off" -warn all [your_regular_command-line_arguments_go_here]
Putting the equivalent in a prefix file will work for IDE users as well.
<iostream.h>, won't build. Why?
You are using <iostream.h> and are seeing these errors:
### /boot/apps/Metrowerks/tools/mwld Linker Error:
# undefined 'ios_base::Init::Init()' (code)
# Referenced from '__sinit_hello_cp' in hello.cp
### /boot/apps/Metrowerks/tools/mwld Linker Error:
# undefined 'cout' (data)
# Referenced from 'main' in hello.cp
# errors caused tool to abort
You are probably failing to specify -lmslcpp on your link line, or do not have libmslcpp.a in your IDE project.
Using BFilePanel may produce errors of similar nature:
### /boot/apps/Metrowerks/tools/mwld Linker Error:
# undefined 'run_open_panel()' (code)
# Referenced from 'Application::MessageReceived(BMessage*)' in main.cpp
You are probably failing to specify -llibtracker.so on your link line (for PPC, on Intel this would be -llibtracker.so.LIB), or do not have libtracker.so in your IDE project (BFilePanel is the only Storage Kit class not implemented in libbe.so). Note that for BeOS Intel, libraries end with an .LIB!
The problem here is that the Be API (the Kits) is implemented in several libraries, and depending on what parts you use, you have to link against several libraries.
To quote from the Be Developer's Guide (page 7):
Library Contents libroot.soProvides access to the kernel; all applications must link with this library. libbe.soContains the Application, Interface, and Support Kits, as well as most of the Storage Kit. All applications should link with this one, too. libGL.soThe OpenGL Kit. libdevice.soThe Device Kit. libgame.soThe Game Kit. libmedia.soThe Media Kit. libmidi.soThe Midi Kit. libmail.soThe library for applications that want to use the mail portions of the Network Kit. libnet.soThe rest of the Network Kit. libnetdev.soThe library for developing a Network Server add-on. libtracker.soContains parts of the Tracker application that can be used by other applications. Currently, the library contains the code for the BFilePanelclass (the API is defined by the Storage Kit).
The warnings you will likely see, if you use the STL part of the ANSI C++ Standard Library, are benign and may be removed with an option to the linker to ignore duplicate-definition warnings. Note however that warnings are your friend and to ignore them means you know exactly what you are doing.
<iostream>s, won't compile. Why?You will probably see this error in the Message Window:
Error : output code size exceeds 64K limit;
# please contact sales@metrowerks.com for info on unlimited linker
You cannot use <iostream>s with the limited linker that comes with the BeOS. The ANSI C++ Standard Library is currently a static library rather than a shared one, since the standard was moving until recently. Thus, if using <iostream> you have to link with this huge lib, and since BeOS ships with CodeWarrior Light, you hit the 64K code limit of the linker [4.2]. This should improve RSN, since the standard is now approved. For serious development under BeOS, you should consider buying the full CodeWarrior anyway.
In the meantime, well, couldn't MW exclude libmslcpp.a from the linker's limit? Hey, it's free. You do not have to use it if you don't want to :-) Metrowerks also does not give away Java. It's light for a reason, and making it not so light would also make it cost money. That's the sad truth.
On the bright side, there is a lightweight version of <iostream> on BeWare at <http://www.be.com/beware/Development.html#iostream.h>. It's a stub that will let you use basic cin << and cout >> functionality.
For staright C development, you can always use GCC, available at <ftp://ftp.ninemoons.com/pub/be/geekgadgets/>. Realize that GCC and C++ is currently a no go on both PCC and x86.
For PPC BeOS, you do have to have the Metrowerks linker since the GNU tools do not handle PEF and may never handle PEF unless Apples license politics change.
For x86 BeOS, the object and executable format is currently PE. The GNU linker and other tools can read object files produced by the Metrowerks linker and the Metrowerks linker also accepts PE object files produced by a GNU toolchain. However, since x86 BeOS uses the same shared library conventions as Windows, and that requires changes to the compiler and other tools to implement, it is not currently possible to use the GNU tools to generate either working objects or executables. The good news is that this problem is simply one of software, not politics or legalities, so it will eventually get fixed.
To summarise, it is unlikely that GCC will be usable for C++ programs that require use the C++ system interfaces for quite some time. Programs written in C++ that only interface to the system using C conventions should work just fine with GCCs own internal C++ runtime layout.
Note that this only applies to BeIDE versions prior to 1.5!
Warning : "Ignoring dup resource in libbe.so MIMS/2/"BEOS:TYPE"
Be has added filetype and version resources to all of the system libraries. During a build associated resources are copied to the executable and now the resources in libbe.so and other libraries are copied, too. Since these are duplicates this warning is generated. To fix this:
The only remaining stock item that has the Has Resources flag turned on should be files with the extension .rsrc.
After making the above changes BeIDE won't try to copy resources from .so files in the project. It will only copy resources from .rsrc files in the project.
mmap()?Hiding and not coming out any time soon. There are no plans to do it for R3. To quote
Dominic Giampaolo:While I'd love to do it but adding features like that will just push out release dates and that's something we'd prefer not to do.
With the Preview Release, Be has specified a standard messaging interface for scriptable applications. This can be implemented in any language that can support sending and receiving BMessage objects.
Despite this, there are two recurring observations:
- 1 -
- This is great. We (and the users) can use whatever language they (the users) prefer. The market will decide what the standard is.
- 2 -
- This is bad. New users need to be able to depend on having a simple language available. {Insert your favorite language here} on the {Insert your favorite OS here} rules the world, and should be the standard on BeOS, too.
- Be's Line -
- The default language shipping with BeOS is sh, so you can always count on that being there. Do not post solicitations or dissertations in an attempt to influence a BeOS scripting standard. The Be List Guy hates those so-called Scripting Wars posts, and will terminate those threads. The Be List Guy, and all of Be, loves working code. Post your code, or better yet, a URL to it, if you want to influence a standard.
If you believe that one true language should be agreed upon (since sh cannot send or receive BMessages on it's own, but instead has to rely on utilities such as hey or tell), write/port it! Post the URL to your ready-to-test/use scripting language, examples, etc. on BeDevTalk. Solicit comments about your implementation from the community on the list when necessary, i.e., when it is of general use to the BeOS programming community.
We all know BeOS is portable. It has already been ported from a strange Hobbit/DSP mixture system to the PowerPC and Intel ... again, there are two re-occurring observations:
- 1 -
- Porting to { my favorite CPU } would expand Be's market and show people that they mean business. On the other hand, if Be doesn't port to { my favorite CPU }, they'll go down in flames.
- 2 -
- Be is a small company and can't afford the resources it'd take to port to { whatever } right now. BTW, { whatever } is a nasty legacy architecture that should've died ages ago, Be is about new beginnings.
- 3 -
- With the next release of the BeOS, Be will be covering both Intel and PowerPC architectures, which covers 99% of the desktop computer systems in the world. Making a compelling business case for porting the BeOS to any processor with less than 1% of the market is very difficult.
- Be's Line -
- <http://www.be.com/support/qandas/beos.html#FAQ-0252>
If you would like to see a particular processor or architecture running the BeOS, contact the processor company and ask them to approach Be about porting to their architecture.
Active == Front is the default behaviour of BeOS. Run /bin/ffm from a Terminal if you want this to change (PR2). To turn it off, run /bin/ffm off (any argument will turn it off).
In R3, you can turn focus-follows-mouse on and off from the Mouse preferences app.
Note: If you run a fullscreen application (BWindowScreen) such as Dominos with ffm turned on, mouse and keyboard input will get ignored, so you cannot Quit(Cmd-Q) the application. Switch to another workspace instead (e.g. Cmd-F2), then close all Domino windows via the Deskbar.
Despite this, BeDevTalk traditionally has two standpoints:
- 1 -
- Focus should be separate from window depth; the default behaviour should be as it is now, but you should have the option of deciding if the focus window is brought to the front or not, and whether the focus follows the mouse pointer or not. Several other options have been suggested.
- 2 -
- The current behaviour should stay the same, end of story. This will prevent new users from being hopelessly confused.
The BeOS file system has support for user/group permissions, and something like the ACLs in Windows NT could easily be implemented using the file attributes.
No other parts of the OS do any security checks or anything but the foundation is there. Be patient and watch BeOS gain multi-user capability before your very eyes.
fork()/exec() inheriting open file descriptors?No.
Despite this, you can in fact use the BeOS much like you would other UNIX boxes.
The system ships with the GNU Bash shell and a full complement of UNIX utilities (awk, sed, grep, rcs tools, diff, make, etc.).
The BeOS is not UNIX (not by a long-shot) nor is it Be's goal to make BeOS be just like UNIX but from an end user standpoint the BeOS shell environment is quite like UNIX.
BeOS, like most UNIXes, is not yet fully POSIX 1003.1 compilant. From a programming standpoint there are a few differences but even there the BeOS C library has not only the strict POSIX functions but also supports some common UNIX functions (such as gettimeofday(), the Berkeley random() function, etc.). A good deal of UNIX code simply recompiles for the BeOS with no modifications, even though most UNIXes are not POSIX 1003.1 compliant either. Things like web servers require a bit more work because of the heavy reliance on UNIX idioms like fork()/exec() inheriting open file descriptors and because sockets are not file descriptors.
If you are using a UNIX box as a single user, the BeOS can pretty much replace it, check BeWare.
If you are using a UNIX box to serve NFS volumes, anonymous FTP, and as a telnet-in MUD server, there currently is no software available that does as good a job of it on BeOS as there is for UNIX. But solutions might become available on BeWare anytime.
Yes.
Because of BeOS's high degree of POSIX compatibility, OpenGL support and standard UNIX commands, BeOS on commodity PowerPC (and soon Intel) hardware can make an excellent replacement for expensive RISC workstations.
In addition, BeOS features an easy-to-program GUI, a basic collection of office apps from third parties (for example BeatWare Basics), and the ability to dual-boot into MacOS or Windows to take advantage of even more software without the performance hit of emulation (unlike a Sun, which can only run Windows applications in emulation, or with an expensive add-on card).
Of course!
With a bundled C++ compiler and IDE environment, BeOS makes a solid platform for learning C/C++ and UNIX/POSIX APIs. Unlike Linux, you do not have to learn X to write powerful GUI apps--the Be Kits make it much simpler. If you feel like hardware hacking, you can write your own device drivers (there are even sample drivers with full source on the Be web site to get you started).
BeOS is also easier to install (no need to edit text files to set up your hard drives, graphics or networking, no need to recompile your kernel) and use (the Tracker lets you manipulate your files with a GUI, even if you are still learning the command-line environment).
You will.
BeOS was designed from the ground up as a high-performance media-oriented OS, with a high-performance 64-bit filesystem, full memory protection, and native support for multiple processors. While there are few AV apps currently available, there are some interesting ones under development. Because BeOS is the natural choice for the next generation of media applications, as more developers realize this, applications will follow.
Not yet.
Because BeOS has some of the attributes of a powerful server OS already (multiprocessor support, multithreading, memory protection, built-in networking, high-performance filesystem, etc.), it is already capable of many useful server tasks (Web and FTP serving, for example).
In fact, basic HTTP, FTP, and telnet servers are bundled with BeOS. However, because there are currently no tools for RAID, multiple users, DNS or email serving, or an SQL database, it is not yet recommended for use as a general purpose UNIX server.
Because it might be easier to rewrite from scratch than to force a square peg through a round hole.
Hail to the new era of multi-threaded everything:
The good part about the BeOS is that it is multi-threaded to the core. One window does its thing; another window does its thing, and they both do these things at the same time.The bad part about most old APIs (say, the Mac Toolbox, Windows SDK, or X Window system) is that they are single-threaded. You ask for an event; you check what window this event was intended for; you handle the event; then you ask for the next event.
Before BeOS, there was nothing iffy about assuming that nobody else would change your global variables, or the variables pertaining to a specific window, while you were using them--unless you were doing interrupt-level stuff.
However, when porting to BeOS, all that changes. Suddenly, all those globals, and all that state, is subject to arbitrary change from anywhere. Just wrapping big locks around everything is not a solution--it's a recipe for disaster.
Take drawing for example: In most APIs, you just focus your destination and draw; the system takes care of displaying what you do. On the Mac, there is even a global that tells you what window you are currently drawing into. On BeOS, you may be drawing into more than one window simultaneously, or you may be wanting to draw into the same window from more than one place, so you have to lock the window you are drawing into. You also have to
Flush()the window you are drawing into to make sure what you are drawing shows up on the screen.The BeOS heralds a whole new era of truly multi-threaded everything, including the UI. There is practically no legacy code in BeOS and you will find that even highly portable code is prepared to deal with this fully multithreaded OS because you can do it right if you start from the ground up. However, for the developer it means that in most cases, existing code will not port cleanly but take heart in the fact that the real joy is in making it work in a multi-threaded environment.
This becomes obvious if you try porting a program that assumes (even forces) a single-threaded event loop API; something like GLUT. It may take three porting attempts to figure out that the correct approach is not to try to port over this code, but to bite the bullet and rewrite those portions from scratch, as C++.
There's a fine line between knowing when to port and when to rewrite. In the case of POSIX code, it is much easier to port. In the case of GUI code, it all depends on the application. Something with a high percentage of portable code with a well-written GUI abstraction layer (like Ghostscript) that only opens a single window can be very straightforward to port. GLUT was better to rewrite from scratch.
If you want to do printf() debugging, you can open a Terminal, start the application that will load your add-on, then any output from that application and the output from your add-on will go to that Terminal.
This will also work with the Tracker and Tracker-add-ons, i.e. you can open a Terminal, shut down the Tracker with Cmd-Alt-Z and restart it from the command line with /boot/beos/system/Tracker&. Then any output from the Tracker will come to your Terminal.
A more complete answer can be found at <http://www.begeek.com/ArticleDisplay.servlet?ArticleID=12>
There is a Be Newsletter article with the recipe for loading and using add-ons <http://www.be.com/aboutbe/benewsletter/Issue82.html#Insight>.
There really are only three basic ways to do plug-ins on BeOS:
- Define an API for each plug-in that uses C function calls; typically one call per function you require of the plug-in. Note that even though the function calls are C, they can take pointers to object as arguments if you feel like it.
- Say that each plug-in should implement a subclass of some class that is known to both your app and the plug-in. It may be a pure virtual class you implement in your app and ship the header for, or it may be a Be system class. Then the plug-in exports one function, whose job it is to take the arguments passed to it and manufacture an object of the defined class and return it to you; further interaction happens through the known virtual member functions of the object.
- Use the Be-defined Replicant functionality. The plug-in has to derive from
BArchivable, and have some way of getting your application aBMessagerepresenting an instance of the class implemented by the plug-in. This works best forBViewsright now, since there is some system level support for un-archivingBViewarchiveBMessagesthat are dropped onBShelfinstances.
You may want to get a copy of Datatypes.lib from BeWare and study how it is put together; it uses mostly method one with some influences of method two.
When linking in a shared (i.e. not static) object under the BeOS, a reference to the shared object is included in the resulting file (executable, add-on, or shared library) so that the run-time loader knows where to look for resolving function and data symbols. The BeOS loader treats a shared object container named _APP_ as a magic reference to the application that is loading an add-on even if the loading application is not the one the add-on was linked against. This feature allows a programmer to replace an older version of an application with a newer one and continue to have all the old add-ons work, as long as the new application exports a super-set of the symbols exported by the old application.
With this in mind there are two ways to link an add-on so that it can use functions or data exported from the loading application:
- Make a copy of the application in question and rename it to _APP_ (exactly these 5 letters). When linking the add-on, include _APP_ in the list of object to link with.
- Create a stub shared library called _APP_ with just the functions and data to be exported and include it in the link command. The stubs do not have to do anything except be a place-holder for the function and data symbols to be exported from the application.
Option 2 is a good choice in a makefile environment because once the stub library is built it will not change (unless one explicitly needs to change or extend which functions or data are exported). In addition, it will not trigger a re-link step for the add-ons.
One of three ways:
- 1. Preferred
- Use the scripting
BMessagesto query theBApplicationfor properties that are the globals. If those globals are yourBWindowsandBHandlers, it is already built intoBApplication; if they are just arbitrary data members, you have to implement those properties yourself (by overridingResolveSpecifier()).
- 2. Pretty good
- Define the API to your add-on such that the application tells the add-on about what the globals are. You may pass in an object of a certain class with only virtual members, and the add-on can call those members to find out. Or you may call an initialization function that passes in data to the add-on.
- 3. Hoakey but useful
- Export the symbols needed from your
BApplication[9.3].
popen()?There are two and a half solutions, with varying drawbacks.
stdin, stdout, and stderr.
load_image() and thread_ids are
BeOS-specific (though you can easily replace them with more
standard fork and exec).
stdin, stdout,
or stderr while this function is executing can be
hazardous, which means you may have to lock large parts of your
app before calling it. A workaround is possible, but pretty ugly.
Email Peter Folk at <pfolk@uni.uiuc.edu> if you really want to know about it.
#include <unistd.h>
#include <be/KernelKit.h>
extern char **environ; /* Your environment (Gift from The
Powers That Be) */
thread_id pipe_command(int argc, char **argv,
int &in, int &out, int &err,
char **envp=environ)
{
// Save current FDs
int old_in=dup(0);
int old_out=dup(1);
int old_err=dup(2);
int filedes[2];
/* Create new pipe FDs as stdin, stdout, stderr */
pipe(filedes); dup2(filedes[0],0); close(filedes[0]);
in=filedes[1]; // Write to in, appears on cmd's stdin
pipe(filedes); dup2(filedes[1],1); close(filedes[1]);
out=filedes[0]; // Read from out, taken from cmd's stdout
pipe(filedes); dup2(filedes[1],2); close(filedes[1]);
err=filedes[0]; // Read from err, taken from cmd's stderr
// "load" command.
thread_id ret=load_image(argc,argv,envp);
// thread ret is now suspended.
// Restore old FDs
close(0); dup(old_in); close(old_in);
close(1); dup(old_out); close(old_out);
close(2); dup(old_err); close(old_err);
/* Theoretically I should do loads of error checking, but
the calls aren't very likely to fail, and that would
muddy up the example quite a bit. YMMV. */
return ret;
}
// In your code...
int in,out,err;
char **argv={"foo","args",NULL};
thread_id tid=pipe_command(2,argv,in,out,err);
if (tid<B_NO_ERROR) explode(tid);
resume_thread(tid);
write(in,"hey\n",strlen("hey\n"));
close(in);
close(out);
close(err);
pipe_command() by passing the command, arguments,
and environment in the normal way:
argv is a NULL-terminated array whose
first element is the command path,
argc is the number of strings in argv, and
envp is a pointer to a NULL-terminated
array of "name=value" pairs which will become the environment
for the command.
int references are assigned the values of pipes
to the command's std{in,out,err} file descriptors.
write() to in.read() from out.read() from
err.fdopen() them into FILE *'s,
or use close() to get rid of them altogether.
The tricky part of the above is the string of pipe(),
dup2(), and close() calls.
write()n to the second can then
be read() from the first) from filedes[1]
to filedes[0] using pipe().
filedes[0] to
stdin (file descriptor (int)0)--so now
the pipe is from filedes[1] to stdin and
filedes[0]. But you only need one of the two recieving
ends of that pipe, so you close(filedes[0]) and save
filedes[1] as the pipe that leads to the new stdin.
filedes[0] and filedes[1], make the writing end of
that pipe out and the other end stdout (file
descriptor (int)1), and close the extra.
err and stderr, and you have your
file descriptors all set up.
Note that now, reading from stdin, or writing to
stdout or stderr, from some other
thread in this team would be a bad thing.
load_image(), it
inherits the file descriptors, after which you can restore your originals
and continue using printf() and fprintf().
resume_thread() or wait_for_thread() with this
ID to start the command.
stdin or stdout easily
available.
#include <stdio.h>
FILE *command=popen("foo args </dev/null 2>/dev/null","r");
/* close unwanted descriptors,
so they don't get in your way */
if (!command) explode();
else {
char buf[512];
fgets(s,512,command);
// ...
int retval=pclose(command);
}
popen() uses the shell to run the command (so beware
of executing commands from untrusted sources), redirecting its
stdin or stdout (depending on whether the
second argument to popen() is "w" or
"r", respectively) to the returned FILE *.
Don't forget to redirect the unused descriptors (you can alias the
command's n'th file descriptor to its m'th
using the shell's "n>&m" syntax) or it will use yours,
and watch out for race conditions.
If you want more control, you can always combine this with the above
pipe() techniques. This allows one to control all three descriptors.
If locking the app to prevent accidental use of std{in,out,err} is absolutely unacceptable but you want to control all three of them, consider the following:
void pipe_command(char *command,FILE *&in,FILE *&out,FILE *&err)
{
int filedes[2], out_fd,err_fd;
pipe(filedes); out_fd=filedes[1]; out=fdopen(filedes[0],"r");
pipe(filedes); err_fd=filedes[1]; err=fdopen(filedes[0],"r");
char *buf=(char *)malloc(strlen(command)+24); // should be ample space
sprintf(buf,"%s 1>&%i 2>&%i",command,out_fd,err_fd);
in=popen(buf,"w");
free(buf);
}
// ...
int retval=pclose(in);
fclose(out);
fclose(err);
In fact, the only reason I recommend *not* using that, is that it's
unsafe and inefficient because it uses the shell, and deadlocks are
harder to avoid because buffering can be erratic.
popen().
FILE *
popen(const char *cmd, const char *type) {
int p[2];
pipe(p); // NOTE: check for failure
if((child_pid = fork()) > 0) { // parent
if (*type == 'r') {
close(p[1]);
fp = fdopen(p[0], type);
} else {
close(p[0]);
fp = fdopen(p[1], type);
}
return fp;
} else if (child_pid == 0) { // child
if (*type == 'r') {
fflush(stdout);
close(1);
dup(p[1]); // NOTE check for error
} else {
close(0);
dup(p[0]);
}
close(p[0]); close(p[1]);
args[0] = "/bin/sh";
args[1] = "-c";
args[2] = (char*)cmd;
args[3] = NULL;
execvp(args[0], args);
}
}
You can easily write your own version to redirect stderr to the pipe in addition to stdout, simply by calling close(2); dup(p[1]); in addition to close(1); dup(p[1]);
One tip: You could eliminate the overhead of an extra copy of bash by changing the args[] array to reflect your actual program command and arguments, instead of running your command through /bin/sh.
Consider
void BView::MouseMoved(BPoint point, uint32 tr, const BMessage* message);
Now you try to override the above with:
void MView::MouseMoved(BPoint point, uint32 tr,BMessage* message);
This method will never get called in reaction to a MouseDown event. Actually you are not overriding the MouseMoved method--you're defining a new method. In this particular case, you need to make the BMessage argument const. In general, the signature of the overriding method must match the overridden one, thus it must take the exact same arguments. No exceptions. This is the same with every virtual method you try to overload!
In this particular case, the warning for Hidden Virtual Functions is the one that, if enabled, will tell you when this happens. It is highly recommended to enable all warnings and check the output after each compile. As already mentioned [6.4], some warnings you will likely see (e.g. if you use the STL part of the ANSI C++ Standard Library) are benign and may be ignored. Nevertheless, the second best thing one can do for some piece of code is to make it compile without warnings (as noted earlier, this is not always possible with the current libraries and compiler). The best thing you can do for your code is to force prototypes for each and every function you will be calling.
MouseUp() isn't ever called. Why?
B_MOUSE_UP events are not dispatched to MouseUp() in BWindow::DispatchMessage(). You have to do this yourself until this is fixed. See <ftp://ftp.be.com/pub/contrib/develop/MessageDemo-0.1.zip>.
Always compile with RTTI and C++ exceptions turned on! Without them on, you will loose Pulse(), MouseDown() and KeyDown().
Apparently libbe.so uses RTTI when dispatching messages. If client code is compiled without RTTI then the dispatching does not work. Exceptions are not related, but all C++ code that uses the Be libraries should be compiled with both of these options turned on. Do not even think of turning them off unless you're sure you know what you're doing.
Also, you will run into problems with the class libraries if you do not have Treat enums as ints checked, as all the Be libraries assume this to be the case.
It is possible for the programmer to do that. Use B_BACKGROUND_APP when setting your application flags.
It is also possible for users to set this with the FileTypes add-on, though the program might override it next time it runs (and thus it is much better if it is done by the author).
FindWindow()?So it can become a FAQ:
Here's a nice (but untested, sorry) FindWindow:
BWindow *FindWindow(const char *title)
{
BWindow *win = NULL;
int32 i = 0;
char *tmptitle;
while ((win = be_app->WindowAt(i)) == NULL) {
win->Lock();
if((tmptitle = win->Title()) != NULL
&& strcmp(tmptitle,title) == 0) {
win->Unlock();
break;
}
win->Unlock();
++i;
}
return win;
}
#include <AppKit.h>
#include <support/List.h>
int main()
{
BApplication("application/x-what-ever");
BList teams;
be_roster->GetAppList(&teams);
app_info ai;
team_id team;
for (int32 i = 0; i < teams.CountItems(); i++) {
team = (team_id)teams.ItemAt(i);
if (be_roster->GetRunningAppInfo(team, &ai) == B_OK) {
printf("team %d: %s\n", ai.team, ai.signature);
}
}
return B_OK;
}
You might want to check out the app_info structure in <app/AppDefs.h> in order to get more information--for example, you can find ai.flags to make sure it is not a background application.
BMessage to a particular BWindow rather than to the BApplication it belongs to?
Once you have an application's BMessenger through the be_roster, you can use the scripting interface to find another BMessenger, even without the other program being specifically designed to do this.
BMessenger app; // this is the application messenger
BMessage msg(B_GET_PROPERTY);
/* notice specifiers are in reverse order */
msg.AddSpecifier("Messenger");
msg.AddSpecifier("Window", 3); /* window number 4 */
BMessage reply; /* (starting from 0) */
app.SendMessage(&msg, &reply);
BMessenger win;
if(reply.FindMessenger("result", &win) == B_OK && win.IsValid()) {
// ...
}
BMessage msg2(B_GET_PROPERTY);
/* this is a "relative path", you could use the app messenger and
add the window specifier */
msg2.AddSpecifier("Messenger");
msg2.AddSpecifier("View", 1); /* view number 2 (starting from 0) */
Message reply2;
win.SendMessage(&msg2, &reply2);
BMessenger view;
if(reply2.FindMessenger("result", &view) == B_OK && view.IsValid()) {
// ...
}
BMessenger for every open BWindow in the Tracker?
Using the scripting interface, you can ask for various properties by index or name. The following program, when compiled and run from the command line, retrieves a BMessenger for each open window in the Tracker. You can modify it to work on other applications, or retrieve other things.
/* this program lists the windows of the tracker as messengers */
#include <Message.h>
#include <Application.h>
#include <Looper.h>
#include <Messenger.h>
#include <Roster.h>
int main()
{
BApplication app("application/x-lister");
entry_ref ref;
if (get_ref_for_path("/system/Tracker", &ref)) {
puts("can't get ref");
return B_ERROR;
}
team_id tracker_team = be_roster->TeamFor(&ref);
if (tracker_team < 0) {
puts("can't get team");
return B_ERROR;
}
status_t err = B_OK;
BMessenger tracker((const char *)NULL, tracker_team, &err);
if (err < 0) {
puts("can't make messenger");
return B_ERROR;
}
int ix = 0;
BMessage query(B_GET_PROPERTY);
BMessage reply;
do {
query.MakeEmpty();
reply.MakeEmpty();
query.AddSpecifier("Window", ix);
err = tracker.SendMessage(&query, &reply);
if (err) {
printf("Query %d error %08x\n", ix, err);
break;
}
printf("Query %d\n", ix);
reply.PrintToStream();
++ix;
} while (reply.what != B_MESSAGE_NOT_UNDERSTOOD);
app.PostMessage(B_QUIT_REQUESTED);
app.Run();
return B_OK;
}
Suppose you have a BFile yourFile and a BView yourView (preferably the size of a mini icon):
BBitmap *iconMap = new BBitmap(BRect(0, 0, B_MINI_ICON - 1,
B_MINI_ICON - 1), B_COLOR_8_BIT);
BNodeInfo mime(yourFile);
mime.GetTrackerIcon(iconMap, B_MINI_ICON);
yourView->SetDrawingMode(B_OP_OVER);
yourView->SetLowColor(B_TRANSPARENT_32_BIT);
yourView->DrawBitmap(iconMap);
delete iconMap;
Error checking is left as an Exercise For The Reader(tm). Check out the header /boot/develop/headers/be/storage/NodeInfo.h on your BeOS machine.
Note that the draw uses a mode where parts of the icon that are transparent (masked out) are not drawn. If you do not care about that, you can skip the SetDrawingMode() and SetLowColor() calls.
Also note that
GetTrackerIcon() does not currently return icons for volumes (use get_device_icon() from
The BeDevTalk FAQ Tutorial 1 demonstrates cursor handling under BeOS. It shows how to specify a cursor, and how/when to make the system show it.
BView the mouse is over, the cursor-setting routine is actually in BApplication. The method BApplication::SetCursor(void* data) takes a pointer to anything and attempts to use it as a cursor. The format of data is documented in the tutorial sourcefile VuCursor.cpp and below. Cursor definitions should be stored in a resource.
BView is needed, a good place to set the cursor is in an override of BView::MouseMoved(). MouseMoved() provides the information of when the cursor enters a BView, moves within it, or leaves a BView. Set a custom cursor when the mouse enters, reset the cursor to the default hand cursor when it leaves. If there are multiple cursors for a given BView, watch the movement within that BView. The only caveat is that notifications of internal movement are only generated when the mouse has moved a few pixels. For a finer control handle the cursor in Pulse() or spawn a separate thread to watch the mouse cursor manually.
BFilePanel to select directories?
Make the filepanel a B_OPEN_PANEL (this is required), and set the node_flavors argument to B_DIRECTORY_NODE.
// --- rw_lock.h ---
#pragma once
const uint32 MAX_READERS = 10000000;
status_t create_rwlock(const char * name);
status_t delete_rwlock(sem_id rwlock);
status_t acquire_read(sem_id rwlock);
status_t acquire_read_etc(sem_id rwlock, bigtime_t timeout);
status_t release_read(sem_id rwlock);
status_t acquire_write(sem_id rwlock);
status_t acquire_write_etc(sem_id rwlock, bigtime_t timeout);
status_t release_write(sem_id rwlock);
// --- rw_lock.cpp ---
#include "rw_lock.h"
status_t create_rwlock(const char * name) {
return create_sem(MAX_READERS, name);
}
status_t delete_rwlock(sem_id rwlock) {
return delete_sem(rwlock);
}
status_t acquire_read(sem_id rwlock) {
return acquire_sem(rwlock);
}
status_t acquire_read_etc(sem_id rwlock, bigtime_t timeout) {
return acquire_sem_etc(rwlock, 1, B_TIMEOUT, timeout);
}
status_t release_read(sem_id rwlock) {
return release_sem(rwlock);
}
status_t acquire_write(sem_id rwlock) {
return acquire_sem_etc(rwlock, MAX_READERS, 0, 0);
}
status_t acquire_write_etc(sem_id rwlock, bigtime_t timeout) {
return acquire_sem_etc(rwlock, MAX_READERS, B_TIMEOUT, timeout);
}
status_t release_write(sem_id rwlock) {
retu rn release_sem_etc(rwlock, MAX_READERS, 0);
}
acquire_sem_etc()) . This means that there is no need to check when the acquisition of the semaphore succeeded, but do check the return code.
There is no such thing as a partial acquisition of a semaphore. You either succeede to acquire the semaphore (as many times as specified with uint32 count) or fail. Failure means that there was no acquisition at all (in total) and thus there is no need to realease anything. You don't try to acquire it six times, but once, and alter the semaphores value by six.
Since the Be counting semaphore implementation enforces FIFO fairness, semaphore acquisition is first come first serve and not serve who is serviceable, so the above implementation will not let writers starve.
In addition to the code above, there is a pretty comprehensive syncronisation library available for BeOS--Betelgeuse, to be found on BeWare.
For additional and more indepth information read the Kernel Kit of the BeBook and get a copy of Operating System Concepts, 4th Edition by A. Silberschatz, Peter Baer Galvin [4.7] and Modern Operating Systems, 2nd Edition by A. S. Tanenbaum [4.7].
It is not possible to implement a Read-Writer-Lock using only one benaphore without introducing a race condition in the code. In case someone does have a solution to this problem, be sure to contact <devsupport@be.com> for a job opportunity.
Related tidbit: The BLocker class is a benaphore.
int64 (long long) using printf()?
int64 some_int64 = 4711;
printf("%Ld", some_int64);
Note the capital L!
Or, using <iostream.h>:
cout << some_int64;
You can send a POSIX signal to a thread through the send_signal() function. The SIGCONT signal tries to unblock a blocked or sleeping thread without killing it; all other signals kill the thread. To override this behavior, you can install your own signal handlers.
If you do this to quit the thread, it can test for its quit boolean (or something else) after each system call, to avoid blocking again right after being dislodged.
When you send_signal() to a thread that is blocked on something, such as a pipe or semaphore, it cancels the blocking operation. That is, the blocking call returns, and the thread resumes running. The call returns an error code indicating that the call was interrupted. POSIX calls set errno to EINTR, BeOS calls return B_INTERRUPTED. Those two are equal error codes.
Note that each thread has a separate errno, so no other thread will change the result unless you do (by calling another blocking operation).
long Random(ulong min, ulong max)
{
long r;
/* Sanity check */
ASSERT(min <= max);
if (min > max) { return(0); }
/* Find range of values. */
max -= min;
/* This ensures that it's (x <= max) as opposed
* to (x < max) */
++max;
/* This is the /recommended/ method for getting a
* number between min and max-1. The high bits are
* more random than the low bits.*/
r = (long) ((double)max*random()/(RAND_MAX+1.0));
return(r+min);
}
ulong Random(ulong max)
{
/* This is the /recommended/ method for getting a
* number between 0 and max-1. The high bits are more
* random than the low bits.*/
return((ulong) ((double)max*random()/(RAND_MAX+1.0)));
}
void Randomize(void)
{
time_t t;
srandom((unsigned) time(&t));
}
Note: random() and the ANSI C rand() are not thread safe [5.5]. Proper synchronization is left as an Exercise To The Reader(tm).
These routines do not use modulo. This is because the periodicity of random() is the bit length of the returned data. Therefore, using modulo would only result in a periodicity of max for this case, whereas using division uses the entire random() value and thus has a higher periodicity.
If you need better random numbers, try finding a lrand48() function which usually comes with any {Net,Free}BSD or Linux libc library.
There is also a /dev/random on BeWare if you need really good random numbers. This will be slightly slower and to save some overhead, you could read a few hundred numbers into a buffer in one operation.
Insert your BeOS CD, wait untill you see the Installer, hit Cmd-Alt-Shift-T, this will open up a Terminal and you should be able to mount any drive via /boot/beos/preferences/DriveSetup&. You should be able to take it from there.
For some reason, the Replicant has grown so much that the little Dragger-Hand is no longer visible, and thus it can't be right-clicked to delete the gone wild Replicant. Find (Tracker Cmd-F) the file named tracker_shelf, shut down the Tracker with Cmd-Alt-Z and restart it from the command line with /boot/beos/system/Tracker& [9.1] or reboot.
Thanks for making this FAQ possible (in the order of the first contact):
Thanks for contributing to this FAQ (in no particular order):
Thanks for suggestions, corrections, submissions and the like (in no particular order):
- extensive AKA's added
- moved [5.4] -> [10.10], [11.2] -> [5.4]
- added FAQ [4.7], [4.8], [5.5], [5.6], [9.3], [9.4], [10.11], [11.2], [N.2], [N.5] (and rearranged existing Q&As in Section N accordingly)
- changes to FAQ [0.0], [1.2], [2.1], [2.2], [2.3], [3.2], [4.1], [4.2], [4.5], [5.1], [5.2], [5.4],[5.5], [6.1], [6.4], [6.5], [7.4], [7.6], [8.1], [10.3], [10.6], [10.7], [10.9], [12.3], [N.3], [N.4]
- released 25.06.1998
- converted into HTML
- some last-minute-corrections und URL-checking
- released 05.02.1998
- folded back Ed Musgrove's suggestions for beta Version 0.9.4
- fundamental punctuation correction
- cleared up the question's capitalisation
- changes to FAQ [7.3]
- folded back Michael A. Alderete's suggestions for beta Version 0.9.3
- overall cosmetic changes and rewording
- changes to FAQ [6.1], [7.2], [7.3]
- folded back Ed Musgrove's suggestions for beta Version 0.9.2
- cosmetic changes to SECTION [1], [2] and [3]
- overall rewording
- changes to FAQ [5.3]
- added FAQ [6.6], [12.3], [4.5], [4.6], [9.2]
- removed [7.6]
- changed History format
- changed versioning scheme retroactive
- added this History
- added Sections [4] Development ([4.1] - [4.4]) and [5] Coding issues ([5.1] - [5.4]) and rearranged existing Sections accordingly, old [8.4] moved to new [5.1]
- cosmetic changes to the header and removed Subject Index:
- folded back Andy Philpotts' suggestions for beta Version 0.9.1
- [3.1] and [3.3] brought in line with the Be posted List Charter
- changes to FAQ [6.3], [6.5], [7.2], [7.4], [8.1], [9.1], [10.1], [10.2], [12.1], [N.1], [N.2], [N.3]
- added FAQ [4.1], [4.2], [4.3], [4.4], [5.1], [5.2], [5.3], [5.4], [7.5], [7.6], [7.7], [7.8], [7.9], [7.10], [7.11], [10.3], [10.4], [10.6], [10.7], [10.8], [10.9], [N.4]