TweetFollow Us on Twitter

C++ Exceptions
Volume Number:11
Issue Number:10
Column Tag:C++ Workshop

Try C++ Exception Handling

How to make use of the C++ exception standard in your C++ code

By Kent Sandvik

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

Exception handling is a feature of the ANSI C++ specification first formally proposed back in 1990, but only recently adopted by compilers on the Macintosh. This has changed with compiler level support for exceptions in CodeWarrior 6, and the promise that Symantec will provide this feature in their C++ compiler soon.

For developers used to working with class libraries, exception handling is nothing new. MacApp, TCL, PowerPlant all have provided macros to implement this feature with setjump/longjmp calls. However, there are still a number of manual steps for the programmer because this technique can interact with compiler optimizations. Supporting exceptions directly in the compiler, which has the ability to make sure that variables and stack information, including C++ objects, are valid between exception cases means that the framework and developers don’t need to worry about these runtime issues. In addition, this means that C++ code is more portable across computer environments.

Most of the C++ literature dealing with exception handling tends to be academic and doesn’t show how C++ exception handling is used in real life. This article will get you started if you want to add standard C++ exception handling into your current project. I will describe what exception handling is, how it works and how to implement exception handling using the proposed ANSI C++ syntax. We will also discuss some pitfalls and design issues.

Error Handling and Exceptions

The generalized model for exception handling is to have, within a part of a program, separate execution paths for normal execution and error recovery. When an error (exception) is detected, the program can ‘throw’ it to the error recovery code (exception handler). The recovery code may then attempt to recover from the error and resume normal program execution, or do some clean up and pass control to the next handler. As noted above, errors are called exceptions, and the error recovery code is called an exception handler.

It is important to note that exception handling is just one of many ways to deal with error cases. The following are some other error reporting techniques used by software engineers:

• Return an error status from the function (OSErr)

• Global error variable (errno in UNIX environments, QDErr and similar low mem globals on the Mac side, fortunately we have functions to return these errors nowadays)

• Invocation of a special, user-defined error function, or callback function

• Jump to a previous point on the stack via setjmp/longjmp

• Use of assertions to test a state, signal if assertion failed

Some examples of error situations are: truly fatal errors, assertions (we assume that something is OK, and it is not), algorithmic failures (like the dreadful one-off with array elements), and alternate return signals (end of file markers arriving with a file stream for instance). As you can see, these are not all fatal errors or errors at all, but they are exceptional cases which can be handled using exception handling.

The beauty of exception handling lies in not only how it relieves the programmer from handling the exceptional situations explicitly, but also allows increased flexibility in dealing with exceptions. For instance, low-level library code needs to signal information about an exceptional condition to the user interface through intervening library code. Let’s say that a network connection is needed and certain C++ objects need to be created to manage it. One part of the code will try to create the objects. If the object creation leads to an unexpected state (suddenly can’t make the connection), the network object could throw an exception back to the code that tries to use it, and at the same time unwind any partially or fully created objects and other variables on the stack.

Should exception handling should be used to handle all these cases, or should it be used selectively?

Several facts speak in favor of using it liberally. The code is cleaner if the error handling is factored out from the normal flow of execution. Error handling code is reused more often, and the actual function blocks would spend less time dealing with error situations across the board, because the task is delegated to specifically designed exception catch blocks that deal uniformly with error situations. Such catch blocks could provide a uniform way of informing end users about error conditions.

On the other hand, because some runtime environments impose a higher runtime overhead on exception processing than normal execution, exception handling should not be used casually as a way to signal information from one part of the call chain to another, or as a quick and dirty way to implement message passing inside an application.

[Some programmers may disagree with this latter assertion. For instance, it is often useful to use an exception as a means of loop termination when it is easier to detect the termination condition and recover than it is to predict it - such as throwing an EOF exception when trying to read past the end of a file. This has the same effect as a break, but can be done several levels deep in the call chain (as you can with longjmp, but more intuitively). In general, I tend to use a 10:1 rule when using an exception within the normal - if the normal case is executed at least 10 times for each time an exception is thrown then an exception is okay. - sgs]

Why Compiler Support for Exceptions is Better

MacApp, TCL and similar frameworks have implemented specific macros and data structures that provide a way to signal exceptions, provide information about the exception, and indicate that a handler that will catch the exception. In most cases these techniques are built around the ANSI C setjmp and longjmp functions. setjmp saves the current program environment inside a jmp_buf data structure. longjmp will let you jump back to the point saved with setjmp. Think of it as a very smart goto that keeps track of the environment setting.

Macro implementations of exceptions work fine, generally, but there are some known problems. Smart compilers like to optimize variables, stuff them into registers or eliminate them. If this happens, the longjmp back to the earlier point might lead to a situation where things are not the same after all. The solution is to declare variable volatile. This is a way to tell the compiler to keep its hands off the variable. Unfortunately, not all compilers have a working volatile keyword. What MacApp had to do in this case was to create a VOLATILE macro. All this macro does is take the address of the variable, which ensures that the compiler (Cfront in this case) will not place this variable into a register. Modern compilers are still pretty keen on optimizing away variables if they have a chance; hopefully such compilers have a working volatile keyword.

Another issue concerns threads and maintaining a linked list of exception handlers. In many cases we want to have a list of exceptions that are valid (for instance the FailInfo implementation of MacApp). If the application spins off threads, and one of these threads throw an exception, there’s a chance we want to roll back to an earlier state. In such cases we want to yank out the exception structure from the linked list. Now, if we don’t keep track of this case with the thread system (for instance, by creating our own thread dispatcher that will know of such data structures and keep the linked list intact), we might yank out the exception frame from the middle of the list and suddenly the linked list is no longer linked.

Also, if we want to roll back to a known state, and this means that there are objects created that should be destructed, it is really up to the programmer to know about this situation.

This is where a compiler level implementation of exception handling is better. Compilers know about what variables should be kept volatile, what data structures are allocated and when these should be destructed and so on. Dealing with threads case is still a tricky one, though. This is a good example where the platform architecture and the language syntax/semantics are not harmonized. C++ does not go far enough to take care of issues related to threads, and it is the the programmer’s responsibility to be alert about this and similar cases.

C++ exception handling ensures that all class instances will be properly de-allocated off the runtime stack or from the heap. This means that we can now take actions in constructors that can fail because it is possible to return an error result by throwing an exception. If a constructor fails, the de-allocation code is called by the compiler, so that we don’t need to worry about memory leaks and non-allocated objects on the stack. For instance, a constructor could try to create files, and if it fails, the destructor will remove them. In other words, constructors are now far more productive.

Needless to say, C++ exception handling requires runtime support. For normal functions the compiler knows where in a program a function is called, and knows where to pick up execution when the function returns. For exception handling the compiler does not know for a particular throw expression what function the catch block resides in, and where execution will resume from after the exception has been handled. These decisions won’t happen until runtime, so the compiler will leave information around for the proper decisions to take place (generates data structures to hold this information needed during runtime). This means additional overhead in the application execution time, stack size and so on.

Exception Basics, Try and Catch

Someone somewhere will signal that they have an exceptional situation. When an exception occurs, an exception handler is triggered on a higher level, and depending on the situation the handler may do any number of things. It is up to the programmer to indicate where exceptions may occur and should be handled. In the following code, the errors are handled in the block marked with the keyword “try”:

 DoSomething()
 {
    // I’m in trouble
 throw exception;
 }

 try {
    DoSomething();  // This will throw an exception, and the catch
    // below will catch it.
 };

 catch (exception)
 {
    // Ooops, what to do?
 }

So what should we do inside the catch block? We might change something and retry the action, return normally (as nothing really happened), rethrow the same exception with modifications and assume that a higher level catch block will help out, throw a different exception, continue execution to the next statement, or just terminate the program.

When we design applications it is important to define what each layer of the application (from the low level utility functions all the way to the end user level) should do with an exception when exceptions are triggered. Various libraries, such as the new ANSI C++ standard library, include exceptions thrown from various class member functions. It is important that the application will catch any relevant exceptions thrown - assuming that the exceptions are documented, of course. We’ll discuss design issues in more detail later.

C++ Exception Coding, Exception Classes

Here’s a more complex example. We implement exceptions that will throw objects instantiated from classes we’ve defined. Let’s investigate each case one at a time:

 try 
 {
 aFoo = new Foo;
 
 aFoo->DoASillyThing(); //This will throw an exception
 }

Here we will do an initialization of a Foo class, and then call a member function that will trigger an unexpected situation (that was hard coded). The try block will tell the compiler that it should catch any exceptions happening from this exercise.

 catch (...) // catch everything
 {
 cerr <<"We catch every single exception here" << endl;
 }

This is the catch block that is usually programmed after the try case. In this first example we will try to catch every possible exception that is bubbling up from the try case (note the ... notation).

However, in most cases it makes sense to specialize on the exceptions that we want to catch. An exception handler can be written to catch only exceptions of a certain class, or a sub-class. (The classes used in our example are described in the next section.) We write:

 catch (TSeriousMacException &ex) // catch only TSeriousMacException
 {
 cerr << "SERIOUS EXCEPTION: " << ex.GetExceptionMessage() <<  
 ",  OSErr: " << ex.GetExceptionOSErr() <<
 ", File: " << ex.GetExceptionFile() << ",  Line: " <<         
 ex.GetExceptionLine() << endl;

    // Use real Mac UI to signal about the seriousness to the user of the application.
 ExitToShell();
 
 }
 
 catch(TMacException &ex) // catch TMacException
 {
 cerr << "EXCEPTION: " << ex.GetExceptionMessage() << ",       
 OSErr: " << ex.GetExceptionOSErr() <<
 ", File: " << ex.GetExceptionFile() << ", Line: " <<          
 ex.GetExceptionLine() << endl;
 }

    // After the exception is handled, we will continue here (not from where the
    // exception was thrown.)

In the above examples, we catch specific exceptions. Note that these exceptions are objects. Exceptions could be strings (“Help”), integers, and various other data structures. The PowerPlant library uses a less elaborate exception structure that is simply a long. In many cases it makes sense to build an exception class hierarchy (more about this later).

Exceptions are caught in a predefined order, top down, from the specific (sub-class) to the generic. This ordering is important. If you catch a parent class exception before the child one, the child exception is never handled. In this case the TSeriousMacException is handled first, even if it’s inherited from the TMacException class. Note also that we will terminate the application with ExitToShell when the TSeriousMacException is caught, otherwise we will continue if the TMacException is handled.

Note that the execution of the code, after the exception in this particular catch block, will continue on the next code line. The execution of the program does not resume where the exception was thrown. However, the catch block could rethrow the exception to a possible next catch block, as in:

 catch(TMacException &ex)
 {
 throw;
 }

The catch block could also modify the current exception object, or throw another exception object, then the next layer or catch frames will take over (assuming these layers exist). Note also that there will not be a recursion if the same exception object is thrown again, in other words the same exception block is not triggered again.

As shown in the example, the exception objects could contain both member functions and fields. This is handy; when we then throw the exception we could provide information back to the catch block about the situation. As we pass the exception object as a reference, we could modify the object, and pass new information along if we want to rethrow the same exception.

A Little More About Exception Classes

We have defined the exception classes to pass information about the error:

class TMacException 
{
public:
 TMacException(const char *theMessage, const OSErr theError) 
 :
 fMessage(theMessage), 
 fError(theError), 
 fFileName("NO FILE SPECIFIED"), 
 fLineNumber(0L) 
 {};
 
 TMacException(const char *theMessage, const OSErr theError,   
 const char *theFileName, const long theLineNumber)            
 :
 fMessage(theMessage), 
 fError(theError), 
 fFileName(theFileName), 
 fLineNumber(theLineNumber) 
 {};
 
 const char*   GetExceptionMessage(void)     { return fMessage;};
 const OSErrGetExceptionOSErr(void){ return fError;};
 const char*GetExceptionFile(void) { return fFileName;};
 const long GetExceptionLine(void) { return fLineNumber;};
 
protected:
 const OSErr   fError;
 const char*   fMessage;
 const char*   fFileName;
 const long fLineNumber;
};


class TSeriousMacException : public TMacException
{
public:
 TSeriousMacException(const char *theMessage, 
  const OSErr theError) 
 : TMacException(theMessage, theError, "NO FILE SPECIFIED",    
 0L) {};
 
 TSeriousMacException(  const char *theMessage, 
 const OSErr theError, 
 const char *theFileName, 
 const long theLineNumber) 
 :  TMacException(theMessage, theError, theFileName,           
 theLineNumber) {};
};

The TMacException is the base class. This class has fields for storing the OSErr, a string message, file name, line number and it could also contain other various fields. We place these fields into a protected area which is why we need inlined accessor member functions (this is not a requirement, but when we do object oriented design, data encapsulation is a good thing to do anyway).

TSeriousMacException is an interesting class, as it does not really contain any additional fields or member functions. Instead, we pass the values back to the TMacException when we construct the exception class. Why? Well, this was a way to signal that this class is more serious than the normal TMacException, and when we look back at the catch block that catches from specific to more generic exceptions we now have a way to signal priority levels to the catch block.

Throwing Exceptions

So far we have shown both the try and catch blocks, but what about throwing exceptions? Here’s finally the DoASillyThing member function:

void Foo::DoASillyThing(void)
{
 throw TMacException("We did a silly thing", unimpErr, 
 __FILE__, __LINE__);
}

or

throw TSeriousMacException("We did a really serious, silly thing", 
 unimpErr, __FILE__, __LINE__);

What we do is to create an exception object as part of the throw action. We could also do things like:

throw “Help me!”;

or

throw anOSErr;

and then we assume that there’s a catch block that will indeed catch such exceptions, strings or OSErr values (or catches any exception). In this example I wanted to write a flexible exception class that contains as much information about the situation as possible, including possible OSErr values and an information string. The __FILE__ and __LINE__ macros for providing information where the exception was triggered also helps out when debugging C++ code. If typing these variables makes your fingers bleed, here’s a macro:

#define THROWEXCEPTION(name, number) \
 throw TMacException( (name), (number), __FILE__, __LINE__)
 
#define THROWSERIOUSEXCEPTION(name, number) \
 throw TSeriousMacException( (name), (number), __FILE__,       
 __LINE__)

PowerPlant defines similar macros as wrap-arounds for OSErr and NULL pointer tests that will throw an exception if the macro test fails.

Note that the object is constructed at the throw point. This might sometimes not look at the case, as in:

enum MyFailures { noErr, bigErr, semiBigErr};
enum myState = noErr;

{
 throw myState;  // we construct the exception object here, not           
    // before!
}

One problem with constructors and destructors in C++ is that they don’t return any values, so usually you need to implement state information fields inside the class and poll these to know what happened after a constructor or destructor was triggered. Exception handling will now help out, as you could throw exceptions from a constructor or destructor, or:

Bar::Bar()
{
 throw TMacException("Problems inside the Bar constructor",    
 noErr, __FILE__, __LINE__);
}

Remember, exception handling should not be used as a way to signal state directly. Instead this is a way to signal other parts of the code that the constructor never completed fully, so the example above is not fully operational. At the same time any partial object or variable content is also purged by the compiler.

Application Design

It is important to fully define how exceptions are triggered, and what parts of the code will intercept and possibly rethrow the exceptions (using the rethrow key word from inside the catch block) to the next level. If this is not fully architected, it will be very hard to know what was going on inside the code when exceptions are triggered.

If you generate objects as part of the initialization of your application, you should try to catch any exceptions that might bubble up from the classes or any class libraries you are using. After this you still need to install catch blocks inside your WaitNextEvent loop block (in some cases the same catch blocks as mentioned earlier). Then depending on the case you might continue with your event handling (and the application), or terminate the program, and if possible provide the end user a chance to save modified data.

Here’s an example of a simple three-level design using exceptions:

Termination

By default when an exception is thrown, and no handlers exist for the thrown exception, the built-in function terminate is called. In the default behavior terminate will call abort (that terminates the program). That means that you need to include the ANSI C library that specifies abort, or then write your own fake abort, as in:

extern "C" void abort(void);

void abort(void)
{
    // Do whatever it takes, DebugStr or whatever...
 ExitToShell();
}

It makes sense to override this function for more control of what is going on, especially if you are using an external C++ library that will throw both known exceptions (documented) and unknown exceptions (not documented). You could override the default terminate function by using the set_terminate function call (note the correspondence with set_new_handler), as in:


void HandleTerminate(void)
{
 cout << "This is the my own terminate function that I've      
 installed!" << endl;
}

set_terminate(HandleTerminate);

Issues

In many cases you want to recover resources when your function is terminated due to exceptions. One practical way is to tie resource recovery to objects. Such objects could live within the scope of the function, and its destructor is called if this object still exists when the function is terminated due to an exception. Such automatic objects mean that you could do less work inside the catch block. Here’s a simplified example:

 void DoSomethingWithMemory(void)
 {
 try {
 TMemoryBlock myHandleObject; // this might even lock the
    // handle
    
    // Do something that might cause an exception to happen
           // if so the TMemoryBlock object’s destructor is called,
    // memory is unlocked, released and so on.
 }
}

Try to recover from exceptions only if you know you can take a reasonable action to correct the situation. End users won’t like if you catch exceptions and continue with the code, and the system crashes milliseconds later due to a low memory corruption situation, for instance. If you don’t know what really happened, it’s better to rethrow the exception upwards than try a random action that might or might not correct the situation.

You could write extended exception classes that have various options, for instance a debug version will drop you to MacsBug signalling situations, while an end user version will maybe provide an alert, or log status information into a text file.

Summary

I have provided a smaller Metrowerks project and C++ code that shows how the various exception parts work together. Feel free to comment and uncomment code lines in order to learn what is happening.

The Annotated C++ Manual (Ellis & Stroustrup) was the de facto standard concerning the exception handling syntax and semantics. The evolving ANSI C++ standard has today taken over the responsibility concerning standardization. The following URLs are handy for finding the latest drafts:

http://www.cygnus.com/~mrs/wp-draft/
ftp://research.att.com/dist/stdc++/WP/

I would also recommend careful reading of the README files for the various C++ compilers; this various compilers might not implement the full standard at this point of time.

As C++ exceptions are a relatively new feature, we will need to refine how we use exceptions based on more practical experience. Also, MacApp, TCL and other frameworks/libraries have exception implemented using macros, and practicing on these platforms is valuable, and in some cases there might not be a need to rewrite exception handling code just so it conforms to ANSI C++, unless code portability and C++ standard following is a big issue.

References

Ellis and Stroustrup, Annotated C++ Reference Manual, Addison-Wesley.

David Reed, “Using C++ Exceptions”, C++ Report, March-April 1994.

David Reed, “Exceptions, Pragmatic Issues With a New Language Feature”, C++ Report, October 1994.

Booch and Vilot, “Designing with Exceptions”, C++ Report, July-August 1993.

Josee Lajoie, “Exception Handling: Supporting First Class Objects”, C++ Report, June 1994.

Taligent, Taligent’s Guide to Designing Programs, Addison-Wesley.

Think Reference 2.0: Example of a setjmp/longjmp implementation.

 
AAPL
$116.17
Apple Inc.
-0.14
MSFT
$47.65
Microsoft Corpora
-1.05
GOOG
$537.79
Google Inc.
+2.96

MacTech Search:
Community Search:

Software Updates via MacUpdate

StatsBar 1.9 - Monitor system processes...
StatsBar gives you a comprehensive and detailed analysis of the following areas of your Mac: CPU usage Memory usage Disk usage Network and bandwidth usage Battery power and health (MacBooks only)... Read more
Cyberduck 4.6 - FTP and SFTP browser. (F...
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more
Maya 2015 - Professional 3D modeling and...
Maya is an award-winning software and powerful, integrated 3D modeling, animation, visual effects, and rendering solution. Because Maya is based on an open architecture, all your work can be scripted... Read more
Evernote 6.0.1 - Create searchable notes...
Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more
calibre 2.11 - Complete e-library manage...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital... Read more
Herald 5.0.1 - Notification plugin for M...
Note: Versions 2.1.3 (for OS X 10.7), 3.0.6 (for OS X 10.8), and 4.0.8 (for OS X 10.9) are no longer supported by the developer. Herald is a notification plugin for Mail.app, Apple's Mac OS X email... Read more
Firetask 3.7 - Innovative task managemen...
Firetask uniquely combines the advantages of classical priority-and-due-date-based task management with GTD. Stay focused and on top of your commitments - Firetask's "Today" view shows all relevant... Read more
TechTool Pro 7.0.6 - Hard drive and syst...
TechTool Pro is now 7, and this is the most advanced version of the acclaimed Macintosh troubleshooting utility created in its 20-year history. Micromat has redeveloped TechTool Pro 7 to be fully 64... Read more
PhotoDesk 3.0.1 - Instagram client for p...
PhotoDesk lets you view, like, comment, and download Instagram pictures/videos! (NO Uploads! / Image Posting! Instagram forbids that! AND you *need* an *existing* Instagram account). But you can do... Read more
SuperDuper! 2.7.3 - Advanced disk clonin...
SuperDuper! is an advanced, yet easy to use disk copying program. It can, of course, make a straight copy, or "clone" -- useful when you want to move all your data from one machine to another, or do... Read more

Latest Forum Discussions

See All

Golfinity – Tips, Tricks, Strategies, an...
Dig this: Would you like to know what we thought of being an infinite golfer? Check out our Golfinity review! Golfinity offers unlimited ways to test your skills at golf. Here are a few ways to make sure your score doesn’t get too high and your... | Read more »
Dark Hearts, The Sequel to Haunting Meli...
Dark Hearts, The Sequel to Haunting Melissa, is Available Now Posted by Jessica Fisher on November 21st, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Meowza! Toyze Brings Talking Tom to Life...
Meowza! | Read more »
Square Enix Announces New Tactical RPG f...
Square Enix Announces New Tactical RPG for Mobile, Heavenstrike Rivals. Posted by Jessica Fisher on November 21st, 2014 [ permalink ] With their epic stories and gorgeous graphics, | Read more »
Quest for Revenge (Games)
Quest for Revenge 1.0.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.0 (iTunes) Description: The great Kingdom of the west has fallen. The gods ignore the prayers of the desperate. A dark warlord has extinguished... | Read more »
Threadz is a New Writing Adventure for Y...
Threadz is a New Writing Adventure for You and Your Friends Posted by Jessica Fisher on November 21st, 2014 [ permalink ] In the tradition of round-robin storytelling, | Read more »
SteelSeries Stratus XL Hardware Review
Made by: SteelSeries Price: $59.99 Hardware/iOS Integration Rating: 4 out of 5 stars Usability Rating: 4.5 out of 5 stars Reuse Value Rating: 4.25 out of 5 stars Build Quality Rating: 4.5 out of 5 stars Overall Rating: 4.31 out of 5 stars | Read more »
ACDSee (Photography)
ACDSee 1.0.0 Device: iOS iPhone Category: Photography Price: $1.99, Version: 1.0.0 (iTunes) Description: Capture, perfect, and share your photos with ACDSee. The ACDSee iPhone app combines an innovative camera, a powerful photo... | Read more »
ProTube for YouTube (Entertainment)
ProTube for YouTube 2.0.2 Device: iOS Universal Category: Entertainment Price: $1.99, Version: 2.0.2 (iTunes) Description: ProTube is the ultimate, fully featured YouTube app. With it's highly polished design, ProTube offers ad-free... | Read more »
Weather or Not - Reports and Forecasts...
Weather or Not - Reports and Forecasts for your Calendar 1.0.0 Device: iOS iPhone Category: Weather Price: $2.99, Version: 1.0.0 (iTunes) Description: Weather or Not is a beautiful and intuitive way to check the weather and... | Read more »

Price Scanner via MacPrices.net

New 13-inch 1.4GHz MacBook Air on sale for $8...
 Adorama has the 2014 13″ 1.4GHz/128GB MacBook Air on sale for $899.99 including free shipping plus NY & NJ tax only. Their price is $100 off MSRP. B&H Photo has the 13″ 1.4GHz/128GB MacBook... Read more
Apple Expected to Reverse Nine-Month Tablet S...
Apple and Samsung combined accounted for 62 percent of the nearly 36 million branded tablets shipped in 3Q 2014, according to early vendor shipment share estimates from market intelligence firm ABI... Read more
Stratos: 30 Percent of US Smartphone Owners t...
Stratos, Inc., creator of the Bluetooth Connected Card Platform, has announced results from its 2014 Holiday Mobile Payments Survey. The consumer survey found that nearly one out of three (30 percent... Read more
2014 1.4GHz Mac mini on sale for $449, save $...
 B&H Photo has lowered their price on the new 1.4GHz Mac mini to $449.99 including free shipping plus NY tax only. Their price is $50 off MSRP, and it’s the lowest price available for this new... Read more
64GB iPod touch on sale for $249, save $50
Best Buy has the 64GB iPod touch on sale for $249 on their online store for a limited time. Their price is $50 off MSRP. Choose free shipping or free local store pickup (if available). Sale price for... Read more
15″ 2.2GHz Retina MacBook Pro on sale for $17...
 B&H Photo has the 2014 15″ 2.2GHz Retina MacBook Pro on sale for $1799.99 for a limited time. Shipping is free, and B&H charges NY sales tax only. B&H will also include free copies of... Read more
New Logitech AnyAngle Case/Stand Brings Flexi...
Logitec has announced the newest addition to its suite of tablet products — the Logitech AnyAngle. A protective case with an any-angle stand for iPad Air 2 and all iPad mini models, AnyAngle is the... Read more
2013 15-inch 2.0GHz Retina MacBook Pro availa...
B&H Photo has leftover previous-generation 15″ 2.0GHz Retina MacBook Pros available for $1499 including free shipping plus NY sales tax only. Their price is $500 off original MSRP. B&H will... Read more
16GB Retina iPad mini on sale today for $199,...
 Staples has 2nd generation 16GB Retina iPad minis on sale for $199 on their online store for a limited time. Their price is $100 off MSRP. Choose free shipping or free local store pickup (if... Read more
Developers Start Designing Apps for Apple Wat...
Apple has announced the availability of WatchKit, software that gives developers a set of tools to easily create experiences designed specifically for Apple Watch. Apple’s developer community can now... Read more

Jobs Board

*Apple* Solutions Consultant (ASC)- Retail S...
**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
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Store Leader Program - College Gradu...
Job Description: Job Summary As an Apple Store Leader Program agent, you can continue your education as you major in the art of leadership at the Apple Store. You'll Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.