C++ tutorial private and protected inheritance? � Assume you’ve seen the standard C++ class (very similar to Java): � Almost never used class MyCls: public BaseCls { � When preceding the name of a base class, private: the private keyword specifies that the public int m_privdata; and protected members of the base class are void f1(); private members of the derived class. protected: � When preceding the name of a base class, int f2(); char m_procdata; the protected keyword specifies that the public: public and protected members of the base char * pubfunc1(); class are protected members of the derived int m_pubdata; class. }; Calling functions in base classes Virtual functions class Mammal { class Window { public: void move() { printf(“mammal move\n”);}; public: //don’t really inline virtual funcs. Like I have here. virtual void speak() { printf(“mammal speak\n”);}; void draw(); }; }; Class Dog: public Mammal { public: class Button: public Window { void move() { printf(“dog move\n”); }; void speak() { printf(“woof\n”); }; public: }; void draw(); int main(void) { }; Mammal * pDog = new Dog; pDog->move(); How do you call Window’s draw()from pDog->speak(); within Button’s draw()? return 0; } 1
How virtual functions (roughly) work Destructors should always be virtual: � When a virtual function is created, the compiler class A { public: builds a virtual function table – has pointer to each ~A() {}; virtual function void func(); }; � One virtual function table per type class B: public A { private: � Each instance of a class has virtual table pointers char * data; public: (vptr) that point to the vtable ~B() { if(data) free(data); }; � The vptr is adjusted in the constructors to point to }; void main(void) the “correct” function { A * a = new B; � Small overhead associated with virtual functions. delete a; //oops... ~B() not called!! } Pure virtual functions The static keyword in classes � In C++, when modifying a data member in a class Mammal { class declaration, the static keyword public: specifies that one copy of the member is shared by all the instances of the class. When virtual void speak()=0; modifying a member function in a class }; declaration, the static keyword specifies that the function accesses only static members. � Speak is a pure virtual function � static member functions may be called � Can’t instantiate a class with pure virtuals without an instance � Derived classes must implement the pure � static data needs to be delcared in the implementation like a global. virtual function or else it can’t be instantiated. 2
Concurrency Concurrency � The two key concepts driving computer systems and applications are � communication: the conveying of information from one entity to another � concurrency: the sharing of resources in the same time frame Haviland – Ch. 8.3.3 � Concurrency can exist in a single processor as well as in a multiprocessor system � Managing concurrency is difficult, as execution behaviour is not always reproducible. Concurrency Example Race conditions � Program a: � Program b � A race condition occurs when multiple processes are trying to do something with shared data and the #!/usr/bin/sh #!/usr/bin/sh count=1 count=1 final outcome depends on the order in which the while [ $count -le 20 ] while [ $count -le 20 ] processes run. do do � E.g., If any code after a fork depends on whether echo -n “ a ” echo -n “ b ” the parent or child runs first. count=`expr $count + 1` count=`expr $count + 1` � A parent process can call wait() to wait for done done termination (may block) � When run sequentially (a; b) output is sequential. � A child process can wait for parent to terminate by � When run concurrently (a&; b&) output is polling (wasteful) interspersed and different from run to run. � Standard solution is to use signals. 3
Example 1 Example 2 Process A Process B Process A Process B x = get(count) y = get(count) x = get(count) y = get(count) Count Count write(x + 1) write(y + 1) write(x + 1) write(y + 1) 1 1 x = 1 y = 1 x = 1 2 write(2) write(2) 2 y = 2 y = 2 3 write(3) write(3) 3 Not what we 2 write(2) The value of count is what we expect. wanted! Example: Race Conditions Producer/Consumer Problem Try running several instances of this #!/bin/sh � Simple example: who | wc –l c=1 � Both the writing process ( who ) and the while [ $c –le 10 ] reading process ( wc ) of a pipeline execute do sd=`cat sharedData` concurrently. sd=`expr $sd + 1` � A pipe is usually implemented as an internal echo $sd > sharedData c=`expr $c + 1` OS buffer. echo d = $sd � It is a resource that is concurrently accessed done #file sharedData must exist and hold by the reader and the writer, so it must be #one integer managed carefully. 4
Producer/Consumer Protecting shared resources � consumer should be blocked when buffer is empty � Programs that manage shared resources must protect the integrity of the shared � producer should be blocked when buffer is full resources. � producer and consumer should run independently as far as buffer capacity and contents permit � Operations that modify the shared resource � producer and consumer should never be updating are called critical sections. the buffer at the same instant (otherwise data � Critical section must be executed in a integrity cannot be guaranteed) mutually exclusive manner. � producer/consumer is a harder problem if there are � Semaphores are commonly used to protect more than one consumer and/or more than one producer. critical sections. Semaphores Critical Sections � Problem: How to execute critical sections in a fair, � Code that modifies shared data usually has symmetric manner? the following parts: � Solutions must satisfy the following: � Entry section : The code that requests permission � Mutual Exclusion: At most one process is in its critical to modify the shared data. section at a time. � Progress: If no process is executing its critical section a � Critical Section : The code that modifies the process that wants to enter can get in shared variable. � Bounded Waiting: No process is postponed indefinitely. � Exit Section : The code that releases access to � An atomic operation is an operation that, once the shared data. started, completes in a logical indivisible way. Most � Remainder : The remaining code. solutions to the critical section problem rely on the existence of atomic operations. 5
General structure Flawed Solution 1 Flawed Solution 2 // process i // process i boolean flag[2]; � Problems? do { do { do { � mutual exclusion not entry section satisfied while(turn != i); flag[i] = true; critical section critical section � Consider: while(flag[ j ]); turn = j; � t0: P0 sets flag[0] to true exit section critical section remainder section remainder section � t1: P1 sets flag[1] to true flag[i] = false; } while(1); � Now both are looping } while(1 ); remainder section forever. } while(1); � Problems? � strict alternation (violates progress rule) A correct solution Problems with the software solution do{ � flag[0] and flag[1] could � The biggest problem with the software both be true, but turn can flag[i] = true; solution to the critical section problem is that have only one value. turn = j; a process waiting to get into the critical region Thus only one process can enter critical section while(flag[ j] && turn == j); is busy-waiting. � progress is preserved critical section � A solution is to take advantage of atomic because process i can flag[i] = false; only be spinning in the hardware instructions and use them to build remainder section loop if turn == j and flag[j] up more general synchronization } while(1); == true. When process j mechanisms like semaphores. exits the critical section, it will set flag[j] to false. 6
Semaphores Flawed implementation of semaphores � A semaphore is an integer variable with two void acquire(int *s) void release(int *s) { { atomic operations: acquire and release. while(*s <= 0); (*s)++; � acquire also called wait, down, P, and lock (*s)--; } � release also called signal, up, V, and unlock } � A process that executes an acquire on a Problems: semaphore variable S, cannot proceed until S � busy-waiting is inefficient is positive. It then decrements S. � does not guarantee bounded waiting � The release operation increments the value � ++ and -- operations are not necessarily atomic of the semaphore variable. Unix (System V) semaphores Unix System V Semaphores � The following pseudo-code protects a critical � Semaphore structures are created and stored section: in the OS kernel, so unrelated processes can use them. acquire(&s); /* critical section */ � A semaphore created and associated with a release( &s ); key, similar to a file handle. /* remainder section */ � One System V semaphore is actually an � What happens if S is initially 0? or 8? array of semaphores. (We will only use one element of the array in discussions in this � We will use System V semaphores to class.) implement acquire and release . 7
More recommend