ee4e. c++ programming lecture 6 advanced topics. contents introduction introduction exception...

46
EE4E. C++ Programming Lecture 6 Lecture 6 Advanced Topics Advanced Topics

Upload: helena-sims

Post on 13-Jan-2016

225 views

Category:

Documents


1 download

TRANSCRIPT

EE4E. C++ Programming

Lecture 6Lecture 6

Advanced TopicsAdvanced Topics

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

Application

Object 1Method call

Error condition

try clause

catch clause

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;}

Program output:Program output:

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

Unsynchronised threads

Thread 1 Thread 2

Update database

Read database

Pre-empt

Pre-empt

Synchronised threads

Thread 1 Thread 2

Update database

Read database

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;}

Program output:Program output:

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;}

Program outputProgram output

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