Advanced C++ Programming assembler using … · Advanced C++ Programming ... Fortran, Cobol as...

Click here to load reader

  • date post

    25-Aug-2018
  • Category

    Documents

  • view

    220
  • download

    1

Embed Size (px)

Transcript of Advanced C++ Programming assembler using … · Advanced C++ Programming ... Fortran, Cobol as...

  • Advanced C++ ProgrammingProgramming is giving new functionality to a computer or computer network.Each programming language is its own a compromis between runtime efficiency and humanreadibility.Examples:

    assembler using mnemonics

    asm {

    pushad

    cpuid ; serial command

    _emit 0x0F ; it is...

    _emit 0x31 ; ... rdtsc

    lea ecx, t

    mov dword ptr [ecx], eax ; # of processor clocks

    mov dword ptr [ecx+4], edx ; if __int64 is used

    popad }

    Fortran, Cobol as formular translators

    C/C++ as general purpose languages

    Lisp/Java as interpreter languages

    The C++ Compiler is just one instrument amoung others to say a computer whats to do,and its a very complex one. The Compiler tries to translate your program text, you should try tounderstand the compiler!!

    1

  • Code symbols.cc// overloading

    int f() {}

    int f(int) {}

    int f(float) {}

    char f(float*, char) {}

    class C

    { public:

    // static methods/functions

    C() {}

    C(int) {}

    static int f() {}

    static int f(char) {}

    // methods

    ~C() {}

    int m() const {}

    virtual int vm() {}

    C &operator=(const C&) {}

    C &operator+(const C&) {}

    };

    C operator*(const C&, int) {}

    2

  • int main()

    { C c,d;

    d = c;

    C::f();

    C::f(0);

    c.m();

    }

    gcc -c symbols.cc -o symbols.o

    3

  • symbol names: nm -C symbols.o

    00000000 W C::~C(void)

    00000000 W C::C(void)

    00000000 W C::operator=(C const &)

    00000028 T operator*(C const &, int)

    00000000 V C virtual table

    00000000 W C::f(void)

    00000000 W C::f(char)

    00000018 T f(float *, char)

    00000010 T f(float)

    00000008 T f(int)

    00000000 T f(void)

    00000000 W C::m(void) const

    00000034 T main

    00000000 W C::vm(void)

    4

  • symbol names: nm symbols.o

    00000000 W _._1C

    00000000 W __1C

    00000000 W __as__1CRC1C

    00000028 T __ml__FRC1Ci

    00000000 W __tf1C

    00000008 C __ti1C

    00000000 V __vt_1C

    00000000 W f__1C

    00000000 W f__1Cc

    00000018 T f__FPfc

    00000010 T f__Ff

    00000008 T f__Fi

    00000000 T f__Fv

    00000000 W m__C1C

    00000034 T main

    00000000 W vm__1C

    The C++ compiler resolves overloading by introducing unique symbol names

    5

  • symbol names (gcc 3.4)

    C::~C(void) _._1CC::C(void) __1C

    C::operator=(C const &) __as__1CRC1Coperator*(C const &, int) __ml__FRC1Ci

    C virtual table __vt_1CC::f(void) f__1CC::f(char) f__1Cc

    C::m(void) const m__C1CC::vm(void) vm__1C

    f(float *, char) f__FPfcf(float) f__Fff(int) f__Fi

    f(void) f__Fv

    6

  • Function namingno return types in symbol name!code

    int f(float);

    char f(float);

    gcc -c symbols.cc -o symbols.o

    symbols.cc:

    In function `char f (float)': symbols.cc:4: new declaration `char f (float)'

    symbols.cc:3:

    ambiguates old

    declaration `int f (float)'

    7

  • Changes: C to C++Philosophy of C: general purpose and near to maschineinherited from C:all fundamental types, pointer types, array types

    void, [unsigned] char, [unsigned] int,..., float, double

    T *, T **, ...

    T[n] (n constant integer)

    pointer to function

    volatile qualifier

    struct

    typedef

    all operators

    unary operators:~, !, -, *, &, [],++, , -> , ., sizeof()

    binary operators: +, - *, /, &, |, ^, &&, ||, ,

    ternary operator: ? :

    8

  • all control structures like

    if() {} [else {}]

    for ( ; ; ) {}

    while() {}

    do {} while();

    asm {}

    standard libraries stdlib, stdio, ...The C preprocessor for #include of declaration header and #define of macros

    9

  • Philosophy of C++ =philosophy of C + o.onew types

    bool

    const qualifier

    reference to type T&

    pointer to member X::*memb

    pointer to method e.g. void (X::*meth() [const]

    classes

    with private, protected and public part, friend declarations

    methods, constructors, destructor, static methods

    The operators new and delete (substituting the typefree malloc and free functions)Inline declarations of functions, overloading of functions

    10

  • The C++ TypesTypes are

    fundamentals (bool, [signed/unsigned]{ char, short int }[long long], float, double [long dou-ble], void, enums

    classes

    pointer to type: Type*

    pointer to function y (*pfType)()

    pointer to method y (C::*pmType)() [const]

    reference to type: Type &

    constant type: const Type == Type const

    11

  • Further Features of C++

    Global functions

    function overloading

    operator overloading

    classes

    constructors

    methods not having the this pointer static methods

    methods having the this pointer virtual methods abstract (virtual) methods > abstract class destructors constant methods

    inheritance multiple inheritance virtual inheritance

    attributes the qualifier mutable

    namespaces

    the using directive

    12

  • Inheritance of classes

    public, private inheritance

    virtual inheritance

    virtual methods

    abstract (virtual methods) and classes

    The standard template library !!Exceptions (as an alternative result) for error handlingFunction- and Operator Overloadingtemplate functions (assumes overloading) and classes

    13

  • The C++ Types

    const Type * == Type const *

    is a (non constant) pointer to constant Type

    Type *const

    is a constant pointer to Type

    const Type *const == Type const*const

    is a constant pointer to a constant Type

    A reference is semantically a constant pointer, syntactically a value.C uses pointer for call by reference, C++ most usually references.For the compiler a (non-virtual) method of the typey (C::*pmType)() [const]is the same as y (*pmType)([const] C* this, args).

    14

  • Why Inheritance ?:

    re-usage of code (of the derived class)

    virtual methods for polymorphy

    interface classes

    15

  • Some Features of the Standard Template LibraryContainer classes in the STL are

    vector

    list

    set

    map

    queue

    A Compare type has to implement the less than policy concerning the type T (Key int the caseof a map), i.e. for a Compare object cmp and T objects t0, t1 the callbool lt = cmp(t0, t1);must be syntactically correct and the implied order must be a total one.The Allocator type need not to be given explicitly. This type has to implement the allocator policy,i.e. the static methods

    static void* allocate(size_t __n)

    static void deallocate(void *, size_t __n)

    must be defined by the Allocator.

    16

  • Iterator Conceptall of these container template classes contain typedefs to iterator and const_iterator and methodswith the signature (i.e. they implement the iterator policy).

    iterator begin()

    const iterator begin() const

    const_iterator end()

    The iterator types implement the pointer policy, i.d. they define:

    iterator operator++ () // post increment

    iterator operator () // post increment

    iterator operator++ (int) // pre increment

    iterator operator (int) // pre decrement

    T *operator -> ()

    T &operator *()

    (The type T* implements automatically the pointer concept!)

    17

  • The std::map implements a mapping from the Key type onto the T type.

    template struct pair

    {

    S first;

    T second;

    };

    A map is like a set whereCompare acts only on the first part of pair.

    The STL also implements the auto_ptr, which implements the owner-ship concept.

    18

  • Resource Management:B. Stroustrup: resource aquisition is initialisationThis means: Put each allocation in its own constructor!Example (by B. Stroustrup)

    class X

    {

    FILE *fp;

    char *mem;

    X(const char * fname, size_t size)

    {

    fp = fopen(fname, r);

    mem = new char[size];

    }

    };

    better:

    class X

    {

    FilePtr fp;

    charPtr memp;

    X(const char *fname, size_t size): fp(fname), memp(size)

    {}

    };

    19

  • In large applications memory leaks are a common problem. This can be handled in a centralmanner using garbage collection schemes or in a distributed manner using smart pointer types.

    smartpointer implementations

    intrinsic (see exercise)

    extrinsic (auto_ptr implemented in the STL and example below)

    (Intrinsic means here: affects the pointed type, extrinsic = non intrinsic)

    20

  • struct reflist

    {

    mutable const reflist *prevM,*succM;

    reflist()

    { prevM = succM = this; }

    reflist(const reflist &p)

    { ref(p); }

    void ref(const reflist &p) const

    { prevM=&p; succM=p.succM;

    succM->prevM = prevM->succM = this;

    }

    void link(const reflist &p) const

    { const reflist *tmp = p.succM;

    succM->prevM = &p; p.succM = succM;

    succM = tmp; tmp->prevM = this;

    }

    bool unref()

    { if(succM!=this)

    { prevM->succM = succM;

    succM->prevM = prevM;

    prevM = succM = this;

    return false;

    }

    return true;

    21

  • }

    const reflist *next() const

    { return succM; }

    bool isShared() const

    { return succM!=this; }

    };

    template class pointerL : public reflist

    {

    void replace(const T* obj)

    { delete(soM);

    soM = (T*)obj;

    for(smartPointerL*i=next(); i!=this; i=i->next())

    i->soM = soM;

    }

    template

    void assign(const smartPointerL &p)

    { if(soM)==p.soM)

    return;

    bool d=unref();

    ref(p);

    if(d) delete(soM);

    soM = p.soM;

    }

    22

  • public:

    template

    smartPointerL(const

    smartPointerL &p):

    reflist(p),soM(p.soM()) {}

    smartPointerL (const smartPointerL &p):

    reflist(p),soM(p.soM) {}

    template

    smartPointerL &operator=

    (const smartPointerL &p)

    { assign(p); return *this; }

    smartPointerL &operator=(const smartPointerL &p)

    { assign(p); return *this;

    template

    const smartPointerL &operator<

  • soM = 0;

    }

    const T &operator*() const

    { return *soM;}

    T &operator*()

    { return *soM; }

    const T* operator->() const

    { return soM;}

    T* operator->()

    { return (T*)soM; }

    };

    24

  • The Late Copy Concept

    template class vectorRep

    { friend class vector;

    uint4 sizeM;

    int4 refCountM;

    void operator delete(void *p)

    { delete[] (char*)p; }

    T tM;

    void *operator new(size_t mysize,size_t size)

    { return new char[mysize + (size-1) * sizeof(T) ]; }

    template vectorRep(uint4 size, const X &x):

    sizeM(size), tM(x)

    { uFill(&tM+1, &tM+sizeM, x); }

    template vectorRep(uint4 size,const X *x,int):

    sizeM(size), tM(*x)

    { uFillP(&tM+1, &tM+sizeM, x+1); }

    vectorRep(uint4 size, const vectorRep &rep,const T &t):

    sizeM(size), tM(rep.tM)

    {

    uint4 m=sizeM

  • {

    for(uint4 i=1; i~T();

    }

    };

    26

  • template functions, inlining of functions;Example sorting:

    template struct stdLess

    { bool operator()(T a, T b) const

    { return a

  • template inline

    void qSort(T *a, T *b, less lt)

    {

    T *i=a, *j=b, *m=a+(b-a)/2, v=*m;

    *m = *a;

    for(;;) {

    while(!lt(*--j, v))

    if(i==j) goto L;

    *i = *j;

    while(!lt(v, *++i))

    if(i==j) goto L;

    *j = *i;

    }

    L:*j++ = v;

    if(i-a>1)

    qSort(a, i, lt);

    if(b-j>1)

    qSort(j, b, lt);

    }

    template inline

    void qSort(T *a, T *b) { qSort(a,b,stdLess()); }

    28

  • inline and non inline compareusage:

    struct point

    {

    double x,y;

    bool operator

  • Binary Searchassuming the elements between a0, a1 are sorted with respect to less

    template inline int lowerBound

    (const T *a0,const T *a1,const T &t,less lt)

    {

    if(a11) {

    const T* m=a0+((a1-a0)> >1);

    if(lt(t,*m)) a1=m;

    else a0=m;

    }

    if(a0==a && lt(t, *a) )

    return -1;

    return a0-a;

    }

    30

  • Meta-Programming ?

    Example: gcd: Z x Z -> Z

    gcd(a,a) = a,a > b gcd(a,b) = gcd(ab,b)

    template struct gcd

    {

    enum { na = a

  • The C++ -Compiler operates on following Objects:Names Id := {identi f ier}Types X := {types}Templates T := {templates}Numbers Z := {integer}(bool := { f alse = 0, true = 1} Z)Functions F := { f unctions}A := X

    Z

    T

    F

    Definitions D := IdAWhere a type IdDn anda Template is of the Form template : XkZmFn> X F .

    class C // (C Id,C X) D{

    typedef type result;// (result Id, type X) Dtemplate class SubC {};

    // (SubC Id,subC T ) Denum { value = 33 };// (value Id,33 Z) D

    };

    32

  • Mapping C -> Meta C++C-Code; Meta C++int x= y; enum {x=y };

    arithmetic expression,x=b%y enum {x= b % y};object; constant integer or type;

    special object e.g. 0 special type, e.g. struct Nil;function template

    int f(double x, int y); template struct Frecursive function call recursive instantiation

    Construction template instantiationconst myType obj(x,y); typedef myTemplate Obj;

    struct myType { int x; }; struct Obj { typedef int X; };obj.x; Obj::X;

    if(); else; template specialisationassignment -

    loop - (needs assignment)

    33

  • int2type: Z -> X

    template struct int2type

    { enum { value = n }; };

    type2type: X -> X

    template struct type2type

    { typedef T result; };

    select: bool x X x X -> X

    template struct select

    { typedef X result; };

    template struct select

    { typedef Y result; };

    reference: X -> X

    template struct reference

    { typedef U& result; enum { is = false }; };

    template struct reference

    { typedef U& result; enum { is = true }; };

    34

  • Example conversion: X x X -> bool

    struct nil

    {

    typedef nil value;

    enum { size = 0 };

    template nil(const T&);

    template struct sub

    { typedef nil result; };

    };

    template struct conversionHelper

    {

    static char f(X x, int);

    static int f(nil, float);

    static const typename reference::result Y_();

    };

    template struct conversion

    {

    typedef conversionHelper H;

    enum { value = sizeof((H::f)((H::Y_)(), 0))==1 };

    };

    template struct inherits

    { enum { value = conversion::value }; };

    35

  • Example property: X -> bool

    template struct property

    {

    enum { value = conversion::value};

    typedef int2type result;

    };

    struct property

    {

    enum { value = true };

    typedef int2type result;

    };// this property is not inherited

    class X

    { ...

    operator property()const;

    // this property is inherited

    };

    36

  • typical usage of properties

    template void f(const X &x, int2type)

    {

    // use: X has property

    }

    template void f(const X &x, int2type)

    {

    // take care of X has not property !!

    }

    template void caller(const X &x)

    { f(x, property::result()); }

    37

  • algorithms acting on types:

    template struct typeTree

    {

    typedef L left; typedef R right; typedef V value;

    typedef typeTree tree;

    enum {leftSize=left::size, rightSize=right::size, size=leftSize+rightSize+1};

    template struct sub

    {

    enum { r = i>leftSize ? i-leftSize : 0 };

    typedef typename select< (i+1==size),

    tree,

    typename right::sub::result>::result rightSub;

    typedef typename select< (i::result result;

    typedef typename result::value value;

    };

    template struct at

    { typedef typename sub::value result; };

    };

    38

  • Example type maps

    template< class Map, class Tree1, class Tree2 = nil> struct map

    {

    typedef typeTree result;

    };

    template< class Map, class Tree> struct map

    {

    typedef typeTree result;

    };

    template< class Map > struct map

    { typedef nil result;};

    39

  • Examples of reasonable type mappings:

    struct lowerType

    {

    template struct map

    { typedef typename select::result result; };

    };

    struct referenceType

    {

    template struct map

    { typedef typename reference::result result;};

    };

    40

  • Example typeTree usage: field: XnZ> X

    template< class Tree, int n=0> struct field :

    public field,

    public field

    {

    typedef Tree tree;

    typedef field leftBase;

    typedef field rightBase;

    typedef typename tree::value value;

    enum { size = tree::size };

    value valM;

    field(): valM(value()) {}

    template field(const field &f):

    leftBase(f), rightBase(f), valM(f.valM) {}

    template field &operator=(const field &f)

    { leftBase::operator=(f);

    rightBase::operator=(f);

    valM = f.valM;

    return *this;

    }

    void print(std::ostream &os) const

    { leftBase::print(os); rightBase::print(os);os<

  • Alexandrescu: Small Object AllocationThe Standard Allocator

    standard allocation/deallocation by new/delete most often thin wrapper of malloc/free general purpose implementation good for medium and large sized blocks but slow for small object (

  • //Platform independend

    struct MemControlBlock

    {

    size_t size;

    bool available;

    };

    //Platform dependend

    struct MemControlBlock

    {

    size_t size :31;

    bool available: 1;

    };

    allocation and dealloction: linear search

    struct MemControlBlock

    {

    MemControlBlock *prev, *next;

    bool available;

    };

    dealloction: no search

    43

  • Small Object Allocator HierarchyGoal: allocation and dealloction (most often) without searchSmallObject: Service on object level, usage by inheritanceSmallObjectAllocator: Allocates small objects of different sizes, configurableFixedAllocator: Allocates small objects of fixed sizeChunk: Handles fixed number of small objects of fixed size

    44

  • ////////////////////////////////////////////////////////////////////////////////

    // class Chunk

    // Offers services for allocating fixed-sized objects

    ////////////////////////////////////////////////////////////////////////////////

    struct Chunk

    { // No Constructor

    void Init(size_t blockSize, unsigned char blocks);

    void* Allocate(size_t blockSize);

    void Deallocate(void* p, size_t blockSize);

    // blockSize not hold

    unsigned char* pData_;

    unsigned char firstAvailableBlock_,

    blocksAvailable_;

    };

    45

  • ////////////////////////////////////////////////////////////////////////////////

    // Chunk::Init

    // Initialise a chunk

    ////////////////////////////////////////////////////////////////////////////////

    void Chunk::Init(size_t blockSize, unsigned char blocks)

    {

    assert(blockSize > 0);

    assert(blocks > 0);

    // Overflow check

    assert((blockSize * blocks) / blockSize == blocks);

    pData_ = new unsigned char[blockSize * blocks];

    firstAvailableBlock_ = 0;

    blocksAvailable_ = blocks;

    unsigned char i = 0;

    unsigned char* p = pData_;

    for (; i != blocks; p += blockSize)

    { *p = ++i; }

    }

    46

  • ////////////////////////////////////////////////////////////////////////////////

    // Chunk::Allocate

    // Allocates a block from a chunk

    ////////////////////////////////////////////////////////////////////////////////

    void* Chunk::Allocate(size_t blockSize)

    {

    if (!blocksAvailable_)

    return 0;

    unsigned char* pResult = pData_ + (firstAvailableBlock_ * blockSize);

    // Set firstAvailableBlock_ to the next available block

    firstAvailableBlock_ = *pResult;

    --blocksAvailable_;

    return pResult;

    }

    47

  • ////////////////////////////////////////////////////////////////////////////////

    // Chunk::Deallocate

    // Deallocates a block from a chunk

    ////////////////////////////////////////////////////////////////////////////////

    void Chunk::Deallocate(void* p, size_t blockSize)

    {

    assert(p >= pData_);

    unsigned char* toRelease = static_cast(p);

    // Alignment check

    assert((toRelease - pData_) % blockSize == 0);

    *toRelease = firstAvailableBlock_;

    // Set firstAvailableBlock_ to position of toRelease

    firstAvailableBlock_ = static_cast((toRelease - pData_) / blockSize);

    // Truncation check (position can be hold by char?)

    assert(firstAvailableBlock_ == (toRelease - pData_) / blockSize);

    ++blocksAvailable_;

    }

    48

  • ////////////////////////////////////////////////////////////////////////////////

    // class FixedAllocator

    // Offers services for allocating fixed-sized objects

    ////////////////////////////////////////////////////////////////////////////////

    class FixedAllocator

    {

    size_t blockSize_;

    unsigned char numBlocks_;

    typedef std::vector Chunks;

    Chunks chunks_;

    Chunk* allocChunk_;

    Chunk* deallocChunk_;

    // For ensuring proper copy semantics

    mutable const FixedAllocator* prev_;

    mutable const FixedAllocator* next_;

    ...

    public:

    // Allocate a memory block

    void* Allocate();

    // Deallocate a memory block previously allocated with Allocate()

    void Deallocate(void* p);

    };

    49

  • ////////////////////////////////////////////////////////////////////////////////

    // FixedAllocator::Allocate // Allocates a block of fixed size

    ////////////////////////////////////////////////////////////////////////////////

    void* FixedAllocator::Allocate()

    {

    if (allocChunk_ == 0 || allocChunk_->blocksAvailable_ == 0)

    {

    Chunks::iterator i = chunks_.begin();

    for (;; ++i)

    {

    if (i == chunks_.end())

    { // Initialize

    chunks_.reserve(chunks_.size() + 1);

    Chunk newChunk;

    newChunk.Init(blockSize_, numBlocks_);

    chunks_.push_back(newChunk);

    allocChunk_ = &chunks_.back();

    deallocChunk_ = &chunks_.front();

    break;

    }

    if (i->blocksAvailable_ > 0)

    {

    allocChunk_ = &*i;

    50

  • break;

    }

    }

    }

    assert(allocChunk_ != 0); assert(allocChunk_->blocksAvailable_ > 0);

    return allocChunk_->Allocate(blockSize_);

    }

    51

  • ////////////////////////////////////////////////////////////////////////////////

    // class SmallObjAllocator

    // Offers services for allocating small-sized objects

    ////////////////////////////////////////////////////////////////////////////////

    class SmallObjAllocator

    {

    public:

    SmallObjAllocator(size_t chunkSize, size_t maxObjectSize);

    void* Allocate(size_t numBytes);

    void Deallocate(void* p, size_t size);

    private:

    SmallObjAllocator(const SmallObjAllocator&);

    SmallObjAllocator& operator=(const SmallObjAllocator&);

    typedef std::vector Pool;

    Pool pool_;

    FixedAllocator* pLastAlloc_;

    FixedAllocator* pLastDealloc_;

    size_t chunkSize_;

    size_t maxObjectSize_;

    };

    52

  • ////////////////////////////////////////////////////////////////////////////////

    // class SmallObject

    // Base class for polymorphic small objects, offers fast allocations/deallocations

    ////////////////////////////////////////////////////////////////////////////////

    class SmallObject

    {

    static void* operator new(size_t size)

    // Trick: Let size be given by compiler

    static void operator delete(void* p, size_t size)

    virtual ~SmallObject() {}

    };

    The compiler is able to get size of destroyed objects by asking the destructor or by adding thissize in virtual function table.

    53

  • Alexandrescu: Singleton Objectsclass Font {...};

    class PrinterPort {...};

    class PrintJob {...};

    class MyOnlyPrinter

    {

    static void AddPrintJob(PrintJob &newJob)

    {

    if(printQueue_.empty() && printingPort_.available())

    { printgPort_.send(newJob.Data());

    else

    { printQueue_.push_back(newJob); }

    }

    private:

    static std::queue printQueue_;

    static PrinterPort printingPort_;

    static Font defaultFont_;

    };

    54

  • class Singleton

    {

    public:

    static Singleton *Instance()

    {

    if(!pInstance_)

    pInstance_ = new Singleton;

    return pInstance_;

    }

    private:

    Singleton() {}

    Singleton(const Singleton&);

    Singleton *pInstance_;

    };

    // Sinleton.cpp

    Singleton* Singleton::pInstance_ = 0;

    55

  • Disadvantages:

    No polymorphy

    Hard initialisation and destruction

    56

  • Singleton sneaky(*Singleton::Instance() );

    // -> Compile error

    class Singleton

    {

    public:

    static Singleton &Instance();

    private:

    Singleton() {}

    Singleton(const Singleton&);

    Singleton& operator=(const Singleton&);

    ~Singleton();

    };

    57

  • Problem Destruction(Singleton constructor may allocate persistant ressources)

    static Singleton &Instance()

    {

    static Singleton Instance;

    return Instance;

    }

    (Meyers singleton, 1996 )Destruction after termination of mainThe compiler generates a function which destructs Singleton::instance.This function is registered by atexit-

    58

  • class Singleton

    {

    public:

    static Singleton *Instance()

    {

    if(!pInstance_)

    {

    if(destroyed_)

    std::runtime_error(bad singleton recognised);

    else

    Create();

    }

    return *pInstance_;

    }

    private:

    static void Create()

    { static Singleton instance;

    pInstance_ = &instance;

    };

    ~Singleton()

    { pInstance_ = 0; destroyed_ = true; }

    };

    59

  • The Phoenix-Singleton: change in last listing

    if(destroyed_)

    std::runtime_error(bad singleton recognised);

    by

    if(destroyed_)

    {

    Create();

    new(pInstance_) Singleton;

    atexit(KillPhoenixSingleton);

    destroyed_ = false;

    }

    and add

    static void KillPhoenixSingleton();

    60

  • Visitor-PatternEnlargement of class hierarchy

    adding class just write new class which inherits one class of hierarchy compile new class

    adding virtual method add virtual method in base if necessary add virtual method to derived classes recompile all of class hierarchy.

    61

  • class shapeI

    {

    public:

    virtual void visit(dispatcherI&) = 0;

    };

    struct rect: public shapeI

    {

    void visit(dispatcherI &V)

    { V.dispatch(*this); }

    static std::string type()

    { return "rect"; }

    };

    struct circle: public shapeI

    {

    void visit(dispatcherI &V)

    { V.dispatch(*this); }

    static std::string type()

    { return "circle"; }

    };

    struct typePrinter: public dispatcherI

    { virtual void dispatch(rect &);

    virtual void dispatch(circle &); };

    62

  • Virtual method call = partial evaluationf (class, param) fclass(param)

    class Base

    {

    ...

    virtual Y method(X x);

    };

    class Object: public Base

    {

    ...

    virtual Y method(X x);

    };

    Object obj;

    Base &b=obj;

    b.method(y);

    translated by compiler to set of functions likeY method(Base *this, X x);

    Y method(Object *this, X x);

    The virtual function call mechanism performs the partial evaluation.

    63

  • MultiMethod-Pattern:partial evaluation of multiple classesf (class,class, ..., param) fclass,class,...(param)

    is not directly supported by C++.But this pattern can be imlemented for example by map:

    --> special impl. of method

  • struct dispatcherI;

    class shapeI

    {

    public:

    virtual void visit(dispatcherI&) = 0;

    };

    struct rect: public shapeI

    {

    void visit(dispatcherI &V)

    { V.dispatch(*this); }

    static std::string type()

    { return "rect"; }

    };

    struct circle: public shapeI

    {

    void visit(dispatcherI &V)

    { V.dispatch(*this); }

    static std::string type()

    { return "circle"; }

    };

    65

  • struct dispatcherI

    { virtual void dispatch(rect &) =0;

    virtual void dispatch(circle &) =0; };

    template struct dispatcherT: dispatcherI

    { T &t;

    dispatcherT(T &s) : t(s) {}

    void dispatch(rect &s)

    { F::call(t, s); }

    void dispatch(circle &s)

    { F::call(t, s); }

    };

    template struct dispatcher: dispatcherI

    { shapeI &shp;

    dispatcher(shapeI &s) : shp(s) {}

    void dispatch(rect &r)

    { dispatcherT dsp(r);

    shp.visit(dsp);

    }

    void dispatch(circle &c)

    { dispatcherT dsp(c);

    shp.visit(dsp);

    }

    };

    66

  • struct intersector

    {

    template static void call(T0&, T1&)

    { std::cout<

  • //IDispatchPart.h

    template< typename TItem > struct IDispatchPart_

    { virtual void Dispatch( TItem& _item ) = 0; };

    //IDispatch.h

    template< typename TItems > struct IDispatcher_ :

    public IDispatchPart_< typename TItems::item > ,

    public IDispatcher_< typename TItems::next > {};

    //Deferred dispatcher interface stub.

    template struct IDispatcher_< ListEnd_ > {};

    //IShapesDsp.h

    class Rect_;

    class Square_;

    class Triangle_;

    class RightTriangle_;

    typedef TypeList_< Rect_,

    TypeList_< Square_,

    TypeList_< Triangle_,

    TypeList_< RightTriangle_ > > > > Shapes_;

    class IShapesDsp_ : public IDispatcher_< Shapes_ > {};

    68

  • 69

  • 70

  • /************************* pair' and lists *********************/

    struct nil {};

    template struct pair

    { typedef pair p;

    typedef L car;

    typedef R cdr;

    };

    template struct listH

    { typedef pair final; };

    template struct listH { typedef nil final; };

    template struct list: listH::final

    { typedef typename listH::final p; };

    71

  • /************************* Eval ************************/

    template struct eval

    { typedef P final; };

    template struct eval

    { typedef val final; };

    template struct eval

    { typedef typename eval::final fun;

    typedef typename instance::final Fun;

    typedef typename eval::final final;

    };

    template struct eval

    { typedef T final; };

    72

  • /************************* macros ************************/

    template struct instance

    { typedef typename Fun:: template fun::final final; };

    template struct instance

    { typedef typename eval::final X1;

    typedef typename Fun:: template fun::final final;

    };

    template struct instance

    { typedef typename eval::final X1;

    typedef typename Fun:: template fun::final final;

    };

    template struct instance

    { typedef typename eval::final X1;

    typedef typename eval::final X2;

    typedef typename Fun:: template fun::final final;

    };

    template struct instance

    { typedef typename eval::final X1;

    typedef typename eval::final X2;

    typedef typename Fun:: template fun::final final;};

    73

  • /************************* REVERSE + Helper ************************/

    template struct reverseH

    { typedef typename reverseH::final final; };

    template struct reverseH

    { typedef Tail final; };

    struct Reverse: macro

    {

    template struct fun

    { typedef quote final; };

    };

    74

  • /************************* MAP ************************/

    template struct mapH

    { typedef transposer

    split;

    typedef typename instance::final fun;

    typedef typename eval::final res;

    typedef pair final; };

    template struct mapH { typedef nil final; };

    struct Map: macro

    {

    template struct fun

    {typedef quote final; }; };

    75

  • Advanced C++ Programming 11.01.05

    keywords:

    solver for systems of equations

    parallelisation

    synchron distributed programming model

    Matrix free solver for nonlinear systems of equations

    f (x) = 0

    The Newton iteration

    f|xnxn = f (xn)

    xn+1 := xn +xn

    reduces this problem to solve a sequence of linear systems.

    76

  • Small linear systems:direct solver (not matrix free!): e.g. reduction by rendering(

    rTc S

    )(x

    )=(

    b

    )

    x = S1b S1c = r

    T S1brT S1c

    template struct matrix

    {

    matrix sub;

    double col[n-1], row[n-1], d, invCol[n-1], invD;

    double dotRow(const double *z) const

    {

    double s=0;

    for(int i=0; i

  • for(int j=0; j

  • void mult(double *y, const double *x) const

    {

    *y = dotRow(x+1) + d * *x;

    sub.mult(y+1, x+1);

    for(int i=1; i

  • void multInv(double *x, const double *y) const

    { *x = *y / d; }

    };

    80

  • Large linear systems:iterative solver (matrix free!): example Krylov space methods

    Ax = b

    Kn(A,b) := span({

    b,Ab,A2b, . . . ,An1b})

    =

    span({

    Akb : k = 0 . . .n1})

    Krylov space methods minimise in the kth iteration step Axb for x Kk(A,b).Their implementation need

    the matrix-vector product Ax,

    vector-vector product < x,y >,

    vector-scalar product x, vector-sum x+ y.

    Examples of Krylov space methods areConjugate Gradient (CG), Lanczos for symmetric positive definite matrices.Generalized Minimal Residual (GMRes), Transposed free Quasi Minimal Residual (tfqmr) andBiCGStab for non symmetric indefinite matrices.

    81

  • Example CG iteration:

    vector Cg::solve(const vector &b,

    const vector &x0, double eps )

    {

    vector r(dim), p(dim), a(dim), x(x0);

    r = p = b - A(x0);

    double rho = Skal_mult(r, r);

    for(int k = 0; rho > eps && k < dim; k++)

    {

    a = A(p);

    double alpha = rho/Skal_mult(a, p);

    x += alpha * p;

    r -= alpha * a;

    double beta = 1.0/rho;

    beta *= (rho = Skal_mult(r, r));

    (p *= beta) += r;

    }

    return x;

    }

    82

  • Why matrix free?Let in the context of the Newton iteration

    A := f|xn.

    Then it holds:

    Ax = f|xnx = fx|xn = lim0

    f (xn + x) f (xn)

    This term can be computed either numerically or analytically as the directional derivative.

    What must be done for parallelisation?

    distribution of data

    communication

    parallelisation of all needed operations

    evaluation of f(x)

    vector-vector-product

    83

  • // generic type representation

    double d=3.14;

    string s=3.14;

    // using pointer to void

    void *gen0=&d, *gen1=&s;

    ...

    double *pd0=(double*)gen0, *pd1=(double*)gen1;

    // using any

    any gen0=d, gen1=s;

    ...

    double *pd0=gen0.cast(), *pd1=gen1.cast();

    84

  • //! class any stores any type and allows safe casts

    class any

    { mutable smartPointer repM;

    void unique()

    { if(repM.isShared())

    repM=repM->clone();

    }

    public:

    any() {}

    template any (const T &t)

    { repM = generic::create(t); }

    any(const any &obj): repM(obj.repM) {}

    template any &operator= (const T &t)

    { repM = generic::create(t); return *this; }

    any &operator = (const any &obj)

    { repM = obj.repM; return *this; }

    template T *cast(const T * =0)

    { unique(); return !repM ? (T*)0 : repM->get((T*)0); }

    template const T *cast(const T * =0) const

    { return !repM ? (T*)0 : repM->get((T*)0); }

    };

    85

  • //! generic representation of arbitrary types

    class generic: public shared

    { ...

    public:

    generic(const std::type_info *id): idM(id) {}

    virtual ~generic() {}

    virtual generic* clone() const=0;

    template static generic* create(const T&t)

    { return create_(t, int2type() ); }

    template T *cast(const T *)

    { return cast_(int2type(), (const T*)0); }

    };

    86

  • //! generic representation of arbitrary types

    class generic: public shared

    {

    private:

    const std::type_info *idM;

    virtual const void *obj() const =0;

    template T* cast_(trueT, const T*)

    { return equal(typeid(T), *getTypeId()) ? (T*)obj() : 0; }

    template T* cast_(falseT, const T*)

    { return equal(typeid(T), *getTypeId() ? (T*)() : dynamic_cast(this); }

    template static generic* create_(const T&t, trueT)

    { return SP(new genRepHas(t) ); }

    template static generic* create_(const T&t, falseT)

    { return SP(new genRepIs(t) ); }

    public:

    ...

    };

    87

  • template struct genRepT: public generic

    { genRepT():generic(&typeid(T)) {} };

    template struct genRepIs :public genRepT, public T

    {

    genRepIs(const T &t): T(t) {}

    genRepIs(const genRepIs &t): genRepT(), T((const T&)t) {}

    generic* clone() const

    { return generic*(new genRepIs(*this) ); }

    const void *obj() const

    { return static_cast(this); }

    };

    template struct genRepHas : public genRepT{

    T tM;

    genRepHas(const T &t): tM(t) {}

    generic* clone() const

    { return SP(new genRepHas(tM) ); }

    const void *obj() const

    { return &tM; }

    };

    88

  • Asynchron algorithmsdata serialisationIf two software-components have to exchange structured data types without sharing any data typedeclaration an abstraction concerning binary representation is needed. The mean ideas are

    any structured type is a composition of simpler types

    there are only a few compositions

    to read a structured data only its binary representation is needed

    fundamentalsThe fundamental types defined in the CTL are:the integral types

    char = bool with values in {0,1}

    char=int1, int2, int4, int8

    unsigned char =uchar=uint1, uint2, uint4, uint8

    and the float types

    real4, real8

    89

  • array

    template class array;

    serialisation as

    os<

  • tupel

    template

    class tupel;

    T0 t0;

    T1 t1;

    ...

    Tmax tmax;

    os<

  • cstring

    template class cstring;

    while(!!str[i])

    os<

  • reference

    template class reference;

    if(!t)

    return os < < true < < int4(-1);

    int4 log = os.getStreamId(t);

    if(log>0) // t is already in the stream

    return os < < true < < log;

    os.addReference(t);

    os<

  • To enable the reader of an reference of type T or a specific any object holding a T,the function ctl::connect() must be called before the reading is invoked, in order to insert thecorresponding reader function into a factory.

    struct polymorphIOBase

    {

    virtual ~polymorphIOBase() {}

    virtual iStream &read(void *&, iStream &) const=0;

    };

    template struct polymorphIO:

    public Base, public polymorphIOBase

    {

    iStream &read(void *&obj, iStream &is) const

    { obj = new T; return is> >*(T*)obj; }

    };

    typedef std::string typeId;

    94

  • class factory

    {

    map ioM;

    public:

    template bool add(T* =0)

    { typedef typename select::result base;

    const typeId type=typeName();

    if(!type)

    return false;

    ioM[type] = new polymorphIO;

    return true;

    }

    template void read(const T *&t,

    const typeId &type,iStream &is)

    { polymorphIOBase *io= ioM[type];

    if(dynamic_cast(io))

    io->read((void*&)t,is);

    else

    t = 0;

    }

    };

    95

  • ExampleThe following class defines two constructors accepting a sparse matrix int the ijv and int the rowby row formats.The ijv format is an array of entries of the form (i,j, value) which has the binary representation:

    array

    The row by row format is an array of rows, where each row has an row i index and a vector ofentries of the form (j, val). Its representation is

    array

    96