ee4e. c++ programming lecture 6 advanced topics. contents introduction introduction exception...
TRANSCRIPT
Contents Introduction Introduction Exception handling in C++Exception handling in C++
An object oriented approach to exception handlingAn object oriented approach to exception handling try-catch try-catch model of exception handlingmodel of exception handling Exception handling exampleException handling example Re-throwing exceptionsRe-throwing exceptions Exception specificationsException specifications
Multi-threadingMulti-threading Thread creationThread creation Thread priorityThread priority Thread synchronisationThread synchronisation
Introduction
We will look at 2 more advanced topics in We will look at 2 more advanced topics in C++C++ Exception handlingException handling Multi-threadingMulti-threading
An object oriented approach to exception handling
Robust C++ programs must include Robust C++ programs must include exception exception handlinghandling
Exceptions are error conditions encountered in Exceptions are error conditions encountered in executing class methodsexecuting class methods Attempting to read past an end of fileAttempting to read past an end of file Attempting to read a file that doesn’t existAttempting to read a file that doesn’t exist Trying to open a malformed URLTrying to open a malformed URL Divide by zeroDivide by zero Taking the square root of a negative numberTaking the square root of a negative number etcetc
Normal error handling (in C) would return Normal error handling (in C) would return an error code (eg. –1)an error code (eg. –1)
class myClass{
public:
int readFile(….){
do{
if (!end_of_file)// read the file
elsereturn –1;
} while not_end_of_file return number_of_bytes_read;
}};
This is a simple sometimes effective method but:This is a simple sometimes effective method but: Sometimes not possible to return a valid error Sometimes not possible to return a valid error
code. code. Not object oriented! No information about the Not object oriented! No information about the
error is contained in the error codeerror is contained in the error code Application code gets ‘polluted’ with error Application code gets ‘polluted’ with error
checking codechecking codeIt would be nice to have all of the error It would be nice to have all of the error
handling in one placehandling in one place The method might not be able to return The method might not be able to return
normally from the error. normally from the error. An example would be if a resource the An example would be if a resource the
method was accessing was not availablemethod was accessing was not available
The try-catch model of exception handling Object-oriented applications comprise the use of Object-oriented applications comprise the use of
pre-defined components (objects) by the pre-defined components (objects) by the application and the interaction between these application and the interaction between these objectsobjects The object cannot know in advance how the The object cannot know in advance how the
application will process any error conditions it application will process any error conditions it encountersencounters
The The try-catchtry-catch mechanism is a means by which mechanism is a means by which errors in object code can be communicated in a errors in object code can be communicated in a consistent way to the calling applicationconsistent way to the calling application
Exception handling example
We will look at a simple example of We will look at a simple example of exception handling involving handling a exception handling involving handling a simple divide by zero errorsimple divide by zero error The exception handler simply prints out The exception handler simply prints out
an error messagean error message However, the key point is that the However, the key point is that the
program doesn’t terminate but allows the program doesn’t terminate but allows the user to continueuser to continue
#include <iostream.h>#include <exception>
class DivideByZeroException : public exception{
public:DivideByZeroException::DivideByZeroException()
: exception("Attempted divide by zero") {}};
double quotient(int num, int den){
if (den==0)throw DivideByZeroException();
return (double)(num)/den;}
int main(){
int number1,number2;double result;cout<<"Enter two integers : ";while (cin >> number1 >> number2){
try {result=quotient(number1,number2);cout << "The quotient is " << result << endl;
}catch(DivideByZeroException &dzException){
cout << "Exception! " << dzException.what() << endl;
}cout << "\nEnter two integers : ";
}return 0;
}
Key point is the calling of Key point is the calling of quotient()quotient() within within the the try try clauseclause quotient()quotient() throws the throws the
DivideByZeroExceptionDivideByZeroException exception using exception using the the throw()throw() keyword if a zero keyword if a zero denominator is inputdenominator is input
This is then caught in the This is then caught in the catchcatch clause clause immediately after the immediately after the trytry clause clause
Re-throwing exceptions Often, the exception handler is unable to Often, the exception handler is unable to
adequately process the exception adequately process the exception For example, it might not be appropriate for the For example, it might not be appropriate for the
exception to be handled within the object in exception to be handled within the object in which the exception was generatedwhich the exception was generated
Typically, the exception is then re-thrown on to Typically, the exception is then re-thrown on to an outer objectan outer object
It is possible to have chains of unhandled It is possible to have chains of unhandled exceptions re-thrownexceptions re-thrown
At some level, the exception must be handledAt some level, the exception must be handled
main
Object 2
Object 1 throws exception
Calls method of
Calls method of
re-throw
handles exception
re-throw
class MyClass1 {
public:MyClass1() {}
void aMethod1(){
try{
throw exception();}catch (exception &caughtException){
cout << "Exception thrown in aMethod1" << endl;
throw;}
}};
class MyClass2 {
public:MyClass2() {}
void aMethod2(){
MyClass1 myObject1;try{
myObject1.aMethod1();}catch(exception &caughtException){
cout << "Exception re-thrown in aMethod2" << endl;
throw;}
}};
int main(){
MyClass2 myObject2;try{
myObject2.aMethod2();}catch(exception &caughtException){
cout << "Exception handled in main" << endl;}
cout << “Program terminates ";return 0;
}
In this simple example, an exception in generated in one object, re-thrown In this simple example, an exception in generated in one object, re-thrown in the handler of the calling object and then handled in the main programin the handler of the calling object and then handled in the main program The program produces the following output:The program produces the following output:
Exception thrown in aMethod1
Exception re-thrown in aMethod2
Exception handled in main
Program terminates
Exception specifications An exception specification (a An exception specification (a throw listthrow list) enumerates a list of exceptions that a function can throw) enumerates a list of exceptions that a function can throw
Indicates that the function throws exceptions Indicates that the function throws exceptions only only of types ExceptionA, ExceptionB, ExceptionC of types ExceptionA, ExceptionB, ExceptionC
If it throws a different type of exception, then function If it throws a different type of exception, then function unexpected() unexpected() is called which normally aborts the is called which normally aborts the programprogramint aFunction(int arg)
throw (ExceptionA, ExceptionB, ExceptionC){ // function body)
(No exception specification.) Indicates that (No exception specification.) Indicates that the function can throw any exceptionthe function can throw any exception
(Empty specification.) Indicates that the (Empty specification.) Indicates that the function cannot throw an exceptionfunction cannot throw an exception If it does, function If it does, function unexpected() unexpected() is calledis called
int aFunction(int arg){ // function body)
int aFunction(int arg)throw(){ // function body)
Comparison with JavaComparison with Java Exception handling almost identical in Exception handling almost identical in
Java and C++ with a few minor syntactic Java and C++ with a few minor syntactic differencesdifferencesThe main difference is a member The main difference is a member
function must advertise when it throws function must advertise when it throws an exception in Javaan exception in Java
This function must then be called in a This function must then be called in a try-catch try-catch clauseclause
int aFunction(int arg) throws IOException // Java{ // function body)
Multi-threading in C++
We are familiar with the idea of multi-tasking We are familiar with the idea of multi-tasking Multi-tasking refers to an operating system Multi-tasking refers to an operating system
running several running several processes processes concurrentlyconcurrently
Each process has its own completely Each process has its own completely independent data independent data
Multi-tasking is difficult to incorporate in Multi-tasking is difficult to incorporate in application programs requiring system application programs requiring system programming primitivesprogramming primitives
However, a single application program can be However, a single application program can be written as a set of written as a set of threadsthreads which run concurrently which run concurrently (in parallel)(in parallel)
A thread is different from a process in that threads A thread is different from a process in that threads share the same datashare the same data
Switching between threadsSwitching between threads involves much less involves much less overhead than switching between programsoverhead than switching between programs
Sharing data can lead to programming Sharing data can lead to programming complications (for example in reading/writing complications (for example in reading/writing databases)databases)
C++ has direct access to low level API C++ has direct access to low level API thread functionsthread functions In contrast to Java and C# which has an In contrast to Java and C# which has an
extra processing layer (within the extra processing layer (within the ThreadThread class)class)
It’s ultimately the OS which provides a It’s ultimately the OS which provides a multithreading capabilitymultithreading capability
C++ therefore more suited to real-time C++ therefore more suited to real-time multi-threading applicationsmulti-threading applications
The chief advantage of writing multi-The chief advantage of writing multi-threaded code is efficiencythreaded code is efficiency Better use is made of the idle time Better use is made of the idle time
common in all applicationscommon in all applicationsWaiting for network connectionsWaiting for network connectionsWaiting for keyboard input Waiting for keyboard input Writing to disk drivesWriting to disk drivesetcetc
A well written application can execute A well written application can execute another task during this idle timeanother task during this idle time
A simple C++ Thread class
A simple A simple ThreadThread class can easily be class can easily be developed enabling multi-threaded developed enabling multi-threaded application to be writtenapplication to be written Similar in use to the Java Similar in use to the Java Thread Thread classclass Makes use of Windows ThreadMakes use of Windows Thread functionsfunctions
class Thread {private:
string m_strName;public:
Thread();Thread(const char* nm);virtual ~Thread();void setName(const char* nm);string getName() const;void start();virtual void run();void sleep(long ms);void suspend();void resume();void stop();void setPriority(int p);bool wait(const char* m,long ms=5000);void release(const char* m);
// Thread prioritiesstatic const int P_HIGHEST;static const int P_LOWEST;static const int P_NORMAL;
}
As in the case of Java, we must override the As in the case of Java, we must override the virtual virtual run()run() method for code to execute in method for code to execute in a separate thread.a separate thread.
Method Method start()start() creates a new thread using creates a new thread using the windows function the windows function CreateThreadCreateThread() and () and calls the calls the run()run() method method
Method Method stop() stop() terminates a thread terminates a thread Methods Methods wait()wait() and and release()release() are for thread are for thread
synchronisation (see later)synchronisation (see later)
Creating a simple multi-threaded application Class Class MyThread MyThread is a derived class ofis a derived class of
ThreadThread The The run() run() method simply increments a method simply increments a
countcount Individual threads are identified by a Individual threads are identified by a
name which is a string passed to the name which is a string passed to the contsructorcontsructor
A A main()main() program creates 2 threads with program creates 2 threads with 2 different names 2 different names
#include <iostream>#include <string>using namespace std;#include "ou_thread.h"using namespace openutils;
class MyThread : public Thread{
private:int m_nCount;
public:MyThread(int n,const char* nm){
Thread::setName(nm);m_nCount=n;
}
void run(){
for (int i=0; i<m_nCount; i++){
cout << getName().c_str() << ":" << i << endl;
}};
#include "MyThread.h"
int main(){
Thread *t1=new MyThread(15,"Thread 01");Thread *t2=new MyThread(10,"Thread 02");
try{
// Start threadst1->start();t2->start();t1->stop();t2->stop();
}catch(ThreadException ex){
cout << ex.getMessage().c_str();}delete t1;delete t2;
return 0;}
Thread synchronization
Each thread pre-empting the other perhaps before Each thread pre-empting the other perhaps before a complete line of output is produceda complete line of output is produced Produces a confusing resultProduces a confusing result Even more serious if the threads are accessing a Even more serious if the threads are accessing a
critical resource such as a database or network critical resource such as a database or network connectionconnection
Threads can be synchronized using Threads can be synchronized using synchronization objects which allow threads synchronization objects which allow threads mutually exclusive access to a resourcemutually exclusive access to a resource
Windows supports various methods of Windows supports various methods of synchronising multi-threaded codesynchronising multi-threaded code SemaphoresSemaphores Event objectsEvent objects Mutex objectsMutex objects
Mutex objects allow one and only one Mutex objects allow one and only one thread to access a mutex object at any one thread to access a mutex object at any one timetime A mutex object is a particular kind of A mutex object is a particular kind of
semaphoresemaphore
The Windows function The Windows function CreateMutex() CreateMutex() is is called to create the mutex objectcalled to create the mutex object Called from the Called from the MutexMutex class constructor class constructor
In the In the run()run() method of method of MyThreadMyThread, we must , we must wait for the mutex object to be released by wait for the mutex object to be released by another threadanother thread
Must remember to release the object once Must remember to release the object once the the run()run() method terminates method terminates
All other methods in All other methods in MyThreadMyThread are the are the samesame
void MyThread::run(){
wait("MyMutex");
for (int i=0; i<m_nCount; i++){
cout << getName().c_str() << ":" << i << endl;}
release("MyMutex");}
int main(){
Thread *t1=new MyThread(15,"Thread 01");Thread *t2=new MyThread(10,"Thread 02");
try{
Mutex m("MyMutex");t1->start();t2->start();t1->stop();t2->stop();m.release();
}catch(ThreadException ex){
cout << ex.getMessage().c_str();}delete t1;delete t2;
return 0;}
The second thread waits until the first The second thread waits until the first thread is finishedthread is finished
Important to call Important to call stop() stop() on all threads in the on all threads in the same order same order start()start() was called was called
The The release()release() function of the function of the MutexMutex class class must be called after the calls to must be called after the calls to stop()stop()
Thread priority
Windows uses the priority level of a thread to Windows uses the priority level of a thread to determine how is allocates slices of CPU timedetermine how is allocates slices of CPU time
Threads have a base priority level by defaultThreads have a base priority level by default The priority can be set with the The priority can be set with the
Thread::setPriority()Thread::setPriority() method method Threads are scheduled in a round robin fashion at Threads are scheduled in a round robin fashion at
each priority leveleach priority level Only when there are no executable threads at a Only when there are no executable threads at a
higher priority level does scheduling at lower higher priority level does scheduling at lower priorities take placepriorities take place
int main(){
Thread *t1=new MyThread(15,"Thread 01");Thread *t2=new MyThread(10,"Thread 02");
try{
t1->start();t1->setPriority(Thread::P_LOWEST);t2->start();t2->setPriority(Thread::P_HIGHEST);t1->stop();t2->stop();
}catch(ThreadException ex){
cout << ex.getMessage().c_str();}delete t1;delete t2;
return 0;}
And finally….. We have looked at exception handling and multi-We have looked at exception handling and multi-
threading in C++ programmingthreading in C++ programming Exception handling is a crucial feature of writing robust Exception handling is a crucial feature of writing robust
error tolerant codeerror tolerant code Its especially important in object oriented programming Its especially important in object oriented programming
as exceptions can be passed up the method calling chain as exceptions can be passed up the method calling chain and handled by the appropriate objectand handled by the appropriate object
Also, in graphical/event handling programs, control is Also, in graphical/event handling programs, control is easily passed back to the event handling thread easily passed back to the event handling thread following an exception without causing the program to following an exception without causing the program to terminateterminate
Writing multi-threaded code can be complexWriting multi-threaded code can be complex C++ differs from Java in that there is no in-built C++ differs from Java in that there is no in-built
ThreadThread class but it is easy to write one using class but it is easy to write one using Windows thread functionsWindows thread functions
Multi-threading is the basis of many applications Multi-threading is the basis of many applications and is particularly crucial in graphical/event and is particularly crucial in graphical/event driven programming as well as real-time systems driven programming as well as real-time systems which control multiple objectswhich control multiple objects
A key feature of multi-threaded code is A key feature of multi-threaded code is synchronising access to shared resources and C++ synchronising access to shared resources and C++ has the flexibility to use a range of methods has the flexibility to use a range of methods including semaphoresincluding semaphores