TweetFollow Us on Twitter

May 92 - Exception Handling in MacApp 3

Exception Handling in MacApp 3

Lonnie Millett

One of the reasons MacApp is successful with developers is that applications built with MacApp can recover and continue operating under conditions that cause other applications to crash. What's the key to creating applications that never crash? It's called exception handling, and understanding how it works is the key to making your own applications fail-safe.

An exception can be defined as any condition which your code cannot be expected to cope with. One common type of exception occurs when trying to allocate memory when there is no memory available. Exception handling "…provides a way of transferring control and information to an unspecified caller that has expressed willingness to handle exceptions of a given type."[1] An exception handler that has expressed willingness to handle a memory exception may be responsible for cleaning up allocations that were made previous to the allocation that failed.

This first article will focus on the mechanics of exception handling in MacApp. By mechanics I am referring to the different usage styles, differences between C++ and Pascal, how it works internally, why and when variables need to be declared VOLATILE, etc. With the mechanics established, a second article will focus on the "how to" of exception handling: when it is needed, when it is not needed, where it goes, and how to introduce it into existing code.

Styles of Exception Handling in MacApp

In MacApp there are two styles of exception handling. The original style of exception handling available since MacApp 1.0, I will refer to as Pascal Style exception handling. It was designed to be used with Object-Pascal and relies on local or global procedures to handle an exception. With MacApp 3.0 a new style of exception handling has been introduced which I will refer to as C++ Style exception handling. Rather than relying on local procedures, it handles an exception within the else clause of an if statement. Neither style of exception handling is exclusive to the language it was designed for. Instances of Pascal style exception handling can be found in the C++ version of MacApp, and C++ style exception handling can be used from Pascal.

Pascal Style Exception Handling

Pascal style exception handling relies on the ability of Pascal to define local procedures as handlers as a way to have access to local variables, procedure parameters, or instance variables. A typical exception handler in Pascal would look like:
PROCEDURE TPicture.IPicture(…);

    VAR fi:     FailInfo;

    PROCEDURE HandleFailure(error: OSErr; message:LONGINT);
    BEGIN SELF.Free; END;

BEGIN
    …
    CatchFailures(fi, HandleFailure);
    fDataHandle := GetPicture(fRsrcID);
    FailResError;
    Success(fi);
    …
END;

We start by declaring an instance of a FailInfo record to contain the information needed by the exception handling services. Among the information stored in the FailInfo record are the current state of all the registers and the address of the procedure that will handle the exception. Later on we will look at the definition of FailInfo in detail. Next we define the local procedure that will be called should an exception occur. Because this is an IMethod, we will want to free ourselves if we can not completely initialize ourselves. In this case the body of the local procedure simply calls SELF.Free. With these two pieces defined we are ready to execute the code that could fail.

In Pascal you bracket any code that could fail with a calls to CatchFailures() and Success(). CatchFailures() requires two parameters: the FailInfo record to store the information necessary to handle the exception and the name of the local procedure to call should an exception occur. CatchFailures() is responsible for storing in the FailInfo record the information needed to pass control to an exception handler. It also installs or links the exception handling information to a list of exception handlers. In the above example, if the call to GetPicture should fail with a resource error, our local procedure HandleFailure() will be called, allowing us to clean up after ourselves. If we successfully retrieved the picture, then we finish our bracketing of the code that could fail with a call to Success(), passing it the same FailInfo record that we passed to CatchFailures(). Success() is responsible for removing the exception handling information from the list of installed exception handlers.

The Exception Handling Chain

MacApp maintains a chain of exception handlers in a linked list, with the current, or last installed, exception handler pointed to by the MacApp global variable gTopHandler. This means that there may be more than one active exception handler installed at any point in time, each scoped to perform certain tasks should an exception occur. This is important. It allows you to define exception handlers that can handle an exception at the local level and not worry about how the exception should be handled at an outer level.

So how does it work? After control is passed to the current exception handler, we usually want the exception to be passed to the other exception handlers in the chain so we can continue to handle the exception in the appropriate manner. With Pascal style exception handling, i.e. when the exception handler is installed with CatchFailures(), this happens automatically. When the global routine Failure() is called, gTopHandler is made to point to the next exception handler in the chain:

pascal void Failure(short error, long message)
{
    FailInfoPtr pf = gTopHandler;

    if (pf)
    {
        // pop the stack first, because calling the handler
        // is likely to result in a call to another call to
        // Failure
        gTopHandler = pf->nextInfo;
        …
        pf->error = error;
        pf->message = message;
        DoFailure(pf);  // Go execute the failure handler
        …

The call to DoFailure() is responsible for passing control to the currently installed exception handler. For Pascal style exception handling, as in our example, DoFailure() would call the local routine HandleFailure(). Following the call to HandleFailure(), DoFailure() calls Failure() once again with the same error and message:

   …
    MoveA.L (A0)+,A0        ; get address of failure handler
    
    Jsr         (A0)        ; call failure handler
                            ; (HandleFailure in our example)

    MoveM.L (SP)+,D0/D1     ; get error & message back
    Move.W  D0,-(SP)
    Move.L  D1,-(SP)        ; parameters to Failure
    Jsr     FAILURE         ; Pass the exception to next
                            ; handler
                            ; should Not return

gTopHandler already points to the next exception handler, so another call to Failure() will pass the exception to the next exception handler in the chain.

If you build debug versions of your MacApp applications you have probably seen something similar to this at one time or another:

Failure caught by: TAPPLICATION.OPENOLD
Failure caught by: CArrayIterator::IArrayIterator(…)
Failure caught by: TODOCCOMMAND.DOIT
Failure caught by: TCOMMANDHANDLER.PERFORMCOMMAND
Failure caught by: TAPPLICATION.POLLEVENT

When an exception occurs, part of the debugging information sent to your favorite source code debugger is a description of the exception stack or chain. Each entry in the list represents a currently installed exception handler. In the example above, TApplication::OpenOld was the last exception handler installed.

The last exception handler in the chain for a running application is usually installed in TApplication::PollEvent. When this exception handler is reached, MacApp assumes that all efforts to handle the exception have already occurred. The only task left is to display the appropriate error alert. After the alert has been displayed, the exception is fully handled, so MacApp continues by processing the event.

What if we don't want to pass the exception to any other installed exception handlers? This might be the case if we can completely handle an exception locally. Since Pascal style exception handling automatically propagates the exception, we have to break the propagation with a Pascal GOTO:

PROCEDURE TPicture.IPicture(…);
    LABEL 1;
    VAR fi:     FailInfo;

        PROCEDURE HandleFailure(
            error: OSErr; message:LONGINT);
        BEGIN
        SELF.Free;
        GOTO 1;
        END;

    BEGIN
    …
    CatchFailures(fi, HandleFailure);
    fDataHandle := GetPicture(fRsrcID);
    FailResError;
    Success(fi);
1:
    …
    END;

As we saw earlier, DoFailure() will call our exception handler, HandleFailure() in this example, if some resource error should occur. Rather than returning to DoFailure() and calling Failure() to propagate the exception, we instead jump to a label we have defined and continue executing from that point without ever returning.

C++ Style Exception Handling

With MacApp 3.0 a new style of exception handling was introduced. Unlike Pascal style exception handling, C++ exception handling is encapsulated in an if statement rather than a local procedure:
pascal void TPicture::IPicture(…)
{
    …
    FailInfo fi;

    if (fi.Try())
    {
        this->SetPictureRsrcID(itsRsrcID, kDontRedraw);
        fi.Success();
    }
    else    // Recover
    {
        this->Free();
        fi.ReSignal();
    }
    …
}

We start as we do in Pascal by declaring an instance of FailInfo. In C++ the FailInfo record of Pascal has been redefined as a C++ class. This class is not derived from TObject and is allocated locally on the stack. We are now ready to bracket the code that could potentially fail. The Try() method of FailInfo has the same responsibilities as CatchFailures() in Pascal. Try() stores information in the fields of the FailInfo instance to pass control back to the If statement should an exception occur. It also links itself into the chain of exception handlers. Finally, Try() returns a boolean TRUE, indicating that it is ready to catch an exception and the If clause of the statement is then executed.

In the above example if the call to SetPictureRsrcID() fails we will automatically jump to the portion of the If statement that tests the return value of Try(). However, this time the value returned is FALSE, so we jump to the ELSE clause of the statement and begin executing the exception handling code. If we were successful in retrieving the picture, we call the Success() method of the FailInfo instance.

Unlike Pascal, C++ style exception handling does not automatically propagate the exception to the next exception handler in the chain. When an exception is bracketed with a Try() instead of CatchFailures(), a JMP rather than a JSR is used to arrive at the exception handler, so we never return to MacApp's exception handling code where it can continue by calling Failure() automatically. If we wish to propagate the exception, we must do so explicitly. This is done at the end of the exception handling code by calling the ReSignal() method of the FailInfo instance. What if we don't want to propagate the exception? C++ style exception handling makes this easy. If we don't include the call to ReSignal(), we continue execution with the first statement following the IF statement.

The Need for VOLATILE

We learned before that when CatchFailures() or Try() is called the current state of all registers is saved. If an exception occurs, the registers are restored to their saved state. But what happens if we modified a variable in the bracketed code that was cached by the compiler in a register? Unfortunately we lose the modified value. This becomes a serious problem if we must then reference the variable in the exception handling part of the code. If, for example, the variable was a newly allocated handle that should be freed on exception, we would lose our reference and would not be able to dispose of it. What is needed is a way to ensure that a variable or parameter is not cached in a register.

The concept of a value being volatile was introduced to do just that. Volatile is a hint to the compiler that the variable in question could change and should not be cached in a register. Volatile is a keyword in both ANSI C and C++. However, Apple's C compiler does not have an implementation of volatile that is sufficient for C++. Therefore, CFront ignores the volatile keyword and does not pass it on to the C compiler. To solve the problem, MacApp 3.0 defines a macro for C++ users called VOLATILE (all upper case). The macro is quite simple:

#define VOLATILE(a) ((void) &a)

By taking the address of a variable or parameter we prevent the compiler from caching it in a register. While this approach currently works for CFront and C, a smarter compiler might optimize the statement away and then go ahead and cache the variable in a register. A different compiler could require a different definition of VOLATILE.

The macro is used like this:

pascal void TWindow::IWindow(TDocument* itsDocument,
                        WindowPtr itsWMgrWindow,
                        …
                        Boolean disposeOnFree)
{
    VOLATILE(itsWMgrWindow);
    VOLATILE(disposeOnFree);

    FailInfo fi;
    if (fi.Try())
    {
        …

Do all variables and parameters need to be declared VOLATILE if we are using exception handling? Thankfully no, since we really do want our compilers to optimize our code as much as possible. The rule for declaring a value as volatile is:

  • Any four-byte or smaller local variable or parameter that is modified in the IF clause of an exception handler and used in the ELSE clause must be declared VOLATILE.

Typical examples are Pointers, Handles, Object references, long or short integer counters, etc.

One more comment about the use of volatile. Those of you who have been using Pascal style exception handling in the current and previous versions of MacApp may be wondering why the use of volatile has never been required. The answer is in the types of optimizations the Pascal compiler can make. When a local or nested procedure is defined, as is always the case for Pascal style exception handling, the Pascal compiler is incapable of optimizing any variable or parameter into a register. Therefore no hints from the developer are required!

C++ Style Exception Handling For Pascal

Neither style of exception handling is exclusive to the language it was initially designed for. With a little effort C++ style exception handling is possible with Pascal in MacApp 3.0. What does it look like?:
PROCEDURE TPicture.IPicture(…);
    VAR fi:     FailInfo;

    BEGIN
    …
    IF Try(fi) THEN
        BEGIN
        SELF.SetPictureRsrcID(itsRsrcID, kDontRedraw);
        Success(fi);
        END
    ELSE
        BEGIN
        SELF.Free;
        Failure(fi.error, fi.message);
        END;
    …

Because FailInfo is not a class in Pascal, we must use the global procedures Try(), Success(), and Failure(), passing our local instance of FailInfo as the parameter. Unfortunately Try() is not externalized in UFailure.p. Part of the extra effort required to use C++ style exception handling in Pascal with MacApp 3.0 is adding a declaration for Try():

FUNCTION Try(VAR fi: FailInfo): BOOLEAN; C; EXTERNAL;

The declaration can be added to your UFailure.p if you are willing to modify your MacApp sources. If not, you can add it to your own source where needed.

The other missing component to support C++ style exception handling in Pascal is a solution for volatile values. Because we are no longer using nested procedures as exception handlers, the Pascal compiler may have optimized local variables and parameters into registers for us. However, unlike C++, Pascal has there is no volatile keyword and no macro capability for extending the language as we did with MacApp 3.0. Luckily we can define a small inline procedure that will serve our purpose nicely:

PROCEDURE VOLATILE(p: UNIV Ptr);
inline 588F;    { ADDQ.L #$4,A7 }

As with the above declaration for Try() this declaration can also be added to your UFailure.p interface or to one of your own headers if you prefer not to modify MacApp. The declarations for both Try() and VOLATILE() have been added to UFailure.p in MacApp 3.0.1, so C++ style exception handling will be fully supported in Pascal.

The same rules apply for determining if a value should be declared VOLATILE in Pascal and C++. However the usage model is slightly different:

PROCEDURE TWindow.IWindow(itsDocument: TDocument,
                        itsWMgrWindow: WindowPtr,
                        …
                        disposeOnFree: BOOLEAN);
    VAR fi: FailInfo;

    BEGIN
    VOLATILE(@itsWMgrWindow);
    VOLATILE(@disposeOnFree);

    IF Try(fi) THEN
        BEGIN
        …

This implementation of VOLATILE requires you to take the address of the variable or parameter that you do not wish the compiler to optimize.

Pascal Style Exception Handling in C++

Pascal style exception handling is still useful in some interesting ways with C++. In particular, MacApp 3.0 uses Pascal style exception handling for certain kinds of value-based or stack-based C++ objects.

Iterators are a special class of value-based objects that can iterate over MacApp's dynamic arrays. One nice feature of dynamic arrays is that iterations can be nested. That is, more than one iterator at a time can be installed for a single dynamic array with each iterator at a different stage of iteration. To make this possible, each dynamic array stores a pointer to a circular list of installed iterators. If during iteration an object becomes inserted into the dynamic array, each of the iterators in the list has its index modified accordingly so that it can continue to iterate properly. When an iterator is finished iterating it removes itself from the list of iterators maintained by its dynamic array.

But what happens if a failure occurs during the iteration? Because an iterator is allocated on the stack it ceases to exist when we exit the iterator's enclosing block and clean up the stack. We need to remove the iterator from the list of iterators maintained by the dynamic array; otherwise it is left with a pointer to an iterator that no longer exists. It's clear that we need an exception handler installed during the life of the iterator so that if an exception occurs the iterator can be removed from the dynamic array's list of iterators.

One of the fields of an iterator is an instance of a FailInfo class. Iterators also have a special method called HandleFailure() which encapsulates the behavior required to unlink the iterator from the list of iterators. During the iterator's IMethod, HandleFailure() is installed with CatchFailures() as the exception handler to be called should an exception occur :

void CArrayIterator::IArrayIterator(…)
{
    …
    // Setup the FailInfo to catch any failures
    // while this object is in scope
    // giving control to the HandleFailure method
    CatchFailures( this->fFailInfo,
        (CatchFailuresType) &CArrayIterator::HandleFailure, this);
} // CArrayIterator::IArrayIterator

As described before, CatchFailures() requires two parameters: an instance of a FailInfo class or record and the procedure to call when an exception occurs. Iterators pass the fFailInfo field as the FailInfo instance and the address of the HandleFailure() method as the method to call. Unlike Pascal we are able to pass the address of methods in C++. But why and how are we able to pass this as a normally non existent third parameter?

CatchFailures() is defined with Pascal calling conventions. Because procedures can be nested in Pascal, a hidden parameter, referred to as the static-link in MacApp, is always passed as the last parameter. If the procedure is nested, the hidden parameter is a pointer to the local scope of that procedure so that it has access to local variables and parameters. If the procedure is not nested, the hidden parameter has a value of NULL. Similar to Pascal, C++ always passes a hidden parameter this to methods for access to the class scope. Because the hidden parameter of Pascal and C++ are both passed as the last parameter to the procedure or method, we can replace the pointer to the static link with a pointer to the class scope of the iterator instance. Now when HandleFailure() is called it will be able to access all of the fields and methods of the instance. If the iterator was successful in iterating over the list, it needs to remove itself from the list of iterators maintained by the dynamic array:

CArrayIterator::~CArrayIterator()
{
    if (fDynamicArray)
    {
        // Remove our entry in the failure handling
        // system as we are going out of scope
        // Use this style of success for efficiency.
        fFailInfo.Success();
        …
    }
} // CArrayIterator::~CArrayIterator

This is done by calling success with the iterator's fFailInfo fields in the class destructor. Why do we use a C++ style call to success rather than a Pascal style when the failure handler was installed with CatchFailures? Actually either one can can be used here but the C++ style call to success is turned into an inline for non-debug builds making it slightly faster to execute.

If we fail during iteration, then the iterator's HandleFailure() will be called:

pascal void CArrayIterator::HandleFailure(OSErr,long)
{
    fDynamicArray->fIteratorPtr = this->RemoveFromList();

    // Check if there is a pending free request that
    // couldn't be honored because we were iterating and if
    // so… be free!
    if (fDynamicArray->fFreeRequested && 
            !fDynamicArray->fIteratorPtr)
        fDynamicArray->Free();

    // the error will be resignalled automatically
    // with the Pascal style of failure handler 
} // CArrayIterator::HandleFailure  

It will take care of removing the iterator from the dynamic arrays list of iterators, honor any requests to free the list which could not be serviced during iteration, and, since we wish to continue propagating the exception to the next exception handler, do nothing, remembering that exception handlers installed with CatchFailures() always resignal an exception automatically.

FailInfo Fields

Part of understanding how exception handling works in MacApp is understanding the fields of the FailInfo record. In C++ FailInfo is defined as a class but is bit-wise compatible with the definition in Pascal:
class FailInfo {
public:
    long        regs[12];   // The saved registers
    short       flags;      // 0 for CatchFailures, 1 for Try
    short       error;      // Error condition passed to Failure
    long        message;    // Failure message
    long        failA6;     // Static-Link passed to Pascal handler
    long        failPC;     // Address of failure handler routine
    FailInfo*   nextInfo;   // Next handler in the chain 
#if qDebug
    long        whoPC;      // Address of the caller
    short       installed;  // Linked into the chain?
#endif
}

When an exception handler is installed with CatchFailures() or Try(), most of the registers, specifically A2-A7 and D2-D7, are saved in regs. If an exception occurs, DoFailures() uses regs to restore the registers to their previous state. The flags field is used to determine how the exception handler was installed. If flags has a value of 0, then the exception handler was installed with CatchFailures() and will need to be called as a procedure. The address of the procedure to be called is stored in failPC, and the link to its local scope is stored in failA6. If the value is 1, then the exception handler was installed with a Try() and DoFailure() will JMP rather than JSR to the address stored in failPC. The failA6 field is unused when using Try(). The error and message fields are set to the value of the parameters passed to Failure() when an exception occurs. These will be passed on to the next exception handler in the chain, pointed to by nextInfo, if the exception handler was installed with CatchFailures() or if the exception is explicitly resignalled.

The last two fields are only available for debug builds of MacApp. The whoPC field points to the instruction following the call to CatchFailures() or Try(). It is used to determine the name of the method that caught the exception. For exception handlers installed with Try(), failPC and whoPC have the same value.

One of the common mistakes made when wrapping code that could cause an exception is forgetting to call Success(). Forgetting to call success can lead to some serious problems. Because the state of all registers including the PC are saved in a FailInfo class, an exception handler that is not removed from the chain by calling Success() could jump to a code segment that has since been unloaded. Debug builds of MacApp warn you the next time you call Success() that you have either too few or too many calls to Success. However, it is sometimes difficult to determine where.

The last field, installed, is available only to C++ users and is used to determine as early as possible that a call to success was forgotten. It is set to TRUE when the exception handler is linked into the chain of exception handlers with CatchFailures() or Try(). If an exception occurs or Success() is called, installed is set to FALSE again. The C++ version of FailInfo defines a destructor for debug builds of MacApp that checks the value of installed. Because the FailInfo destructor is only called if no exception occurred, a value of TRUE indicates that we forgot to call Success(), and we are informed immediately.

FailInfo Methods

In addition to the fields that are common between the Pascal and C++ definitions of FailInfo, C++ adds some useful methods:
class FailInfo {
public:
    inline FailInfo::FailInfo()
    inline Boolean FailInfo::Try(> {return ::Try(*this);}
    inline void FailInfo::ReSignal()
                            {::Failure(error, message);}
#if qDebug
    inline FailInfo::~FailInfo();
    inline void FailInfo::Success() {::Success(*this);}
#else
    inline void FailInfo::Success() {gTopHandler = nextInfo;}
#endif
}

For non-debug builds of MacApp all the methods are defined as inline, so the resulting code looks very much like what you get when doing C++ style exception handling in Pascal. The only difference is the Success() method. Debug builds of MacApp continue to call the global procedure Success() because it will perform some useful debug checks. Non-debug builds optimize Success() so that it only does the required work of unlinking the exception handler from the chain of exception handlers.

Conclusion

Exception handling is an important part of MacApp and is the key to developing applications that respond in a consistent manner under varying conditions. With an understanding of the mechanics of exception handling we are better able to discuss how exception handling can be used in your applications. In the next article I will define the ground rules that are essential to understanding when and how to integrate exception handling. I will also work through some typical examples in MacApp, look at ways of reducing the number of exception handlers that might be required, and try to answer some of the more esoteric questions developers have about exception handling.
 
AAPL
$98.38
Apple Inc.
-0.64
MSFT
$43.89
Microsoft Corpora
-0.09
GOOG
$585.61
Google Inc.
-4.99

MacTech Search:
Community Search:

Software Updates via MacUpdate

Drive Genius 3.2.4 - Powerful system uti...
Drive Genius is an OS X utility designed to provide unsurpassed storage management. Featuring an easy-to-use interface, Drive Genius is packed with powerful tools such as a drive optimizer, a... Read more
Vitamin-R 2.15 - Personal productivity t...
Vitamin-R creates the optimal conditions for your brain to work at its best by structuring your work into short bursts of distraction-free, highly focused activity alternating with opportunities for... Read more
Toast Titanium 12.0 - The ultimate media...
Toast Titanium goes way beyond the very basic burning in the Mac OS and iLife software, and sets the standard for burning CDs, DVDs, and now Blu-ray discs on the Mac. Create superior sounding audio... Read more
OS X Yosemite Wallpaper 1.0 - Desktop im...
OS X Yosemite Wallpaper is the gorgeous new background image for Apple's upcoming OS X 10.10 Yosemite. This wallpaper is available for all screen resolutions with a source file that measures 5,418... Read more
Acorn 4.4 - Bitmap image editor. (Demo)
Acorn is a new image editor built with one goal in mind - simplicity. Fast, easy, and fluid, Acorn provides the options you'll need without any overhead. Acorn feels right, and won't drain your bank... Read more
Bartender 1.2.20 - Organize your menu ba...
Bartender lets you organize your menu bar apps. Features: Lets you tidy your menu bar apps how you want. See your menu bar apps when you want. Hide the apps you need to run, but do not need to... Read more
TotalFinder 1.6.2 - Adds tabs, hotkeys,...
TotalFinder is a universally acclaimed navigational companion for your Mac. Enhance your Mac's Finder with features so smart and convenient, you won't believe you ever lived without them. Tab-based... Read more
Vienna 3.0.0 RC 2 :be5265e: - RSS and At...
Vienna is a freeware and Open-Source RSS/Atom newsreader with article storage and management via a SQLite database, written in Objective-C and Cocoa, for the OS X operating system. It provides... Read more
VLC Media Player 2.1.5 - Popular multime...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more
Default Folder X 4.6.7 - Enhances Open a...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click... Read more

Latest Forum Discussions

See All

Note Review
Note Review By Jennifer Allen on July 29th, 2014 Our Rating: :: TOO SIMPLEiPhone App - Designed for the iPhone, compatible with the iPad Note is a note taking app that’s a little too short on features to be worth its asking price... | Read more »
Chainsaw Warrior Goes on Sale & Ther...
Chainsaw Warrior Goes on Sale & There’s a Chance to Win a Copy of the Original Board Game Posted by Jennifer Allen on July 29th, 2014 [ permalink | Read more »
It Came From Canada: Tiny Tower Vegas
If you go to a casino, you might make a lot of money. If you run a casino, you’re guaranteed to make a lot of money. The choice seems pretty obvious. So while waiting for your shady real estate deals to move forward, get prepared with Tiny Tower... | Read more »
Z Hunter Review
Z Hunter Review By Lee Hamlet on July 29th, 2014 Our Rating: :: RIGHT ON TARGETUniversal App - Designed for iPhone and iPad While it might not necessarily break new ground, Z Hunter has enough tricks up its sleeve to ensure that... | Read more »
Huge Update Comes To Duet, Adding 48 New...
Huge Update Comes To Duet, Adding 48 New Stages Posted by Jennifer Allen on July 29th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Sharknado: The Video Game Available Now....
Sharknado: The Video Game Available Now. Seriously. Posted by Rob Rich on July 29th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Frog Orbs 2 Review
Frog Orbs 2 Review By Nadia Oxford on July 29th, 2014 Our Rating: :: THIS MAGIC IS A TAD MONOTONOUS Universal App - Designed for iPhone and iPad Frog Orbs 2 is repetitive, but younger players should enjoy it nonetheless.   | Read more »
Puzzix Review
Puzzix Review By Jennifer Allen on July 29th, 2014 Our Rating: :: NICE IDEAUniversal App - Designed for iPhone and iPad A little like Tetris, Puzzix is all about piecing together blocks and watching them vanish. It could do with... | Read more »
Cannonball eMail is Now Live – Works Wit...
Cannonball eMail is Now Live – Works With Gmail, Yahoo, Outlook, Hotmail, and AOL Posted by Jessica Fisher on July 29th, 2014 [ permalink ] | Read more »
To The End Review
To The End Review By Lee Hamlet on July 29th, 2014 Our Rating: :: A VICIOUS CYCLEUniversal App - Designed for iPhone and iPad To The End will test players’ patience, timing, and dedication as they try to navigate all 13 levels in... | Read more »

Price Scanner via MacPrices.net

The lowest prices on leftover Retina MacBook...
Best Buy has dropped prices on leftover 13″ and 15″ Retina MacBook Pros by up to $300 off original MSRP on their online store for a limited time. Choose free local store pickup (if available) or free... Read more
Apple Updates MacBook Pro with Retina Display...
Apple today updated its MacBook Pro with Retina display with faster processors and double the amount of memory in both entry-level configurations. MacBook Pro with Retina display features a Retina... Read more
Up to $250 price drop on leftover 15-inch Mac...
B&H Photo has dropped prices on 2013 15″ Retina MacBook Pros by as much as $250 off original MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.3GHz Retina MacBook Pro: $2349... Read more
Updated MacBook Pro Price Trackers
We’ve updated our MacBook Pro Price Trackers with the latest information on prices, bundles, and availability on the new 2014 models from Apple’s authorized internet/catalog resellers as well as... Read more
Apple updates MacBook Pros with slightly fast...
Apple updated 13″ and 15″ Retina MacBook Pros today with slightly faster Haswell processors. 13″ models now ship with 8GB of RAM standard, while 15″ MacBook Pros ship with 16GB across the board. Most... Read more
Apple drops price on 13″ 2.5GHz MacBook Pro b...
The Apple Store has dropped their price for the 13″ 2.5GHz MacBook Pro by $100 to $1099 including free shipping. Read more
Apple drops prices on refurbished 2013 MacBoo...
The Apple Store has dropped prices on Apple Certified Refurbished 13″ and 15″ 2013 MacBook Pros, with model now available starting at $929. Apple’s one-year warranty is standard, and shipping is free... Read more
iOS 8 and OS X 10.10 To Support DuckDuckGo As...
Writing for Quartz, Dan Frommer reports that Apple’s forthcoming iOS 8 and OS X 10.10 operating systems version updates will allow users to select DuckDuckGo as their default search engine. He notes... Read more
U.K. Hospital Using iPods and iPads To Record...
British news journal GazetteLive’s. Ian McNeal notes that the old “an apple a day keeps the doctor away” proverb is being turned on its head at http://southtees.nhs.uk/hospitals/james-cook/ James... Read more
13-inch 2.5GHz MacBook Pro on sale for $1099,...
Best Buy has the 13″ 2.5GHz MacBook Pro available for $1099.99 on their online store. Choose free shipping or free instant local store pickup (if available). Their price is $100 off MSRP. Price is... Read more

Jobs Board

Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.