Øvelse+10+-+Resource+Handling

=Exercise 1 Ensuring garbage collection on dynamically allocated std::string= This is a basic exercise where we revisit the RAII idiom once more, however this time in an enhanced form, where our goal is to extend it with the SmartPointer idiom. Recap: If we inspect the code from the ScopedLock class (or idiom) - see below - it becomes apparent that we have no way of accessing the data residing inside the class. These are considered private and, in the specific use case, sacred in order for the idiom to work as intended.



The questions that comes to mind are:
 * What do we do if we need access?
 * Under which circumstances is this a necessity?
 * What syntax and semantics do we want?

This is exactly what is achieved by combining both the RAII and the SmartPointer idiom. In this exercise your task is to combine the above two mentioned idioms and write a class that encapsulates a std::string, such that garbage collection is enforced when leaving scope and that we get pointer like semantic syntax/usage.

Implement the below shown UML class SmartString: Questions to answer:
 * Why must the copy constructor and assignment operator be private with no implementation?
 * //Copy constructor and assignment operator should be made private to ensure that the Smart String can not be copied in any way.//
 * What exactly does the operator -> do?
 * //Operator> is used to access the string object directly through the Smart String object.//

code format="cpp"
 * SmartPointer.hpp**
 * 1) include
 * 2) include 

class SmartString { private: std::string* str_ //Pointer to string

SmartString(const SmartString& other){} operator=(const SmartString& other){}

public: SmartString(std::string* str_); ~SmartString; std::string* get; std::string* operator->; std::string& operator*; } code

code format="cpp" /* * Since the smart pointershould behave like a pointer, * it should support the same interface as a pointer do. * They should support Dereferencing(operator*) and Indirection(operator->) */
 * SmartPointer.cpp**
 * 1) include "SmartString.hpp"

SmartString::SmartString(std::string* str_) : str_(str_) {

}

SmartString::~SmartString { //Pointer no longer needed delete str_ }

std::string* SmartString::get { return *str_ }

std::string* SmartString::operator-> { return str_ }

std::string& SmartString::operator* { return *str_ } code

=Exercise 2 The Counted Pointer= In this exercise we are going to extend our ne SmartString, such that multiple parties may have a \reference" to it. Since we want sharing of the data as opposed to what we did in Exercise 1, the assignment operator and copy constructor must now be implemented.

This leads to this new interface: Things to be aware and consider: SmartString::SmartString(const SmartString& other) : str_(other.str_), counter_(other.counter_) { //Copy constructor //Copy the str_ //and increment the counter_ (*counter_)++; } code code format="cpp" > SmartString& SmartString::operator=(const SmartString& other) > { > //Asignment operator > if(this != &other) > { > //Decrement the counter_ > //if counter_ become zero delete counter_ > if(counter_-- == 0) > { > delete str_; > delete counter_; > } > > //Copy the str_ and counter > //and increment the reference counter > str_ = other.str_; > counter_ = other.counter_; > (*counter_)++; > } > return *this; > } > code code format="cpp" > SmartString::~SmartString > { > //Destructor > //Decrement the counter_ > //if counter_ become zero delete the data > if((*counter_)--== 0) > { > delete str_; > delete counter_; > } > > } > code
 * Why must the counter be dynamically allocated? Where should this happen?
 * The counter is dynamically allocated in the constructor when a new object is created
 * How is the copy constructor be implemented?
 * code format="cpp"
 * How is the assignment operator be implemented?
 * What happens in the destructor and how should it be implemented?

Create appropriate test harnesses to validate that your solution works. These test harnesses must be part of your documentation on the wiki.

code format="cpp"
 * SmartString.hpp**
 * 1) include
 * 2) include 

class SmartString { private: std::string* str_; //Pointer to string unsigned int* counter_;

public: SmartString(std::string* str_); ~SmartString; std::string* get; std::string* operator->; std::string& operator*; SmartString(const SmartString& other); SmartString& operator=(const SmartString& other); }; code

code format="cpp" /* * Since the smart pointershould behave like a pointer, * it should support the same interface as a pointer do. * They should support Dereferencing(operator*) and Indirection(operator->) */
 * SmartString.cpp**
 * 1) include "SmartString.hpp"

SmartString::SmartString(std::string* str_) : str_(str_) { counter_ = new unsigned int; (*counter_)++; }

SmartString::~SmartString { //Destructor //Decrement the counter_ //if counter_ become zero delete the data if(--(*counter_)== 0) {   delete str_; delete counter_; }

}

std::string* SmartString::get { return str_; }

std::string* SmartString::operator-> { return str_; }

std::string& SmartString::operator* { return *str_; }

SmartString::SmartString(const SmartString& other) : str_(other.str_), counter_(other.counter_) { //Copy constructor //Copy the str_ //and increment the counter_ (*counter_)++; }

SmartString& SmartString::operator=(const SmartString& other) { //Asignment operator if(this != &other) {  //Decrement the counter_ //if counter_ become zero delete counter_ if(counter_-- == 0) {   delete str_; delete counter_; }

//Copy the str_ and counter //and increment the reference counter str_ = other.str_; counter_ = other.counter_; (*counter_)++; } return *this; } code

code format="cpp"
 * Main.cpp**
 * 1) include "SmartString.hpp"

int main {   std::cout << "Test af contructor:" << std::endl << std::endl;

//Oprettelse af ss

SmartString ss(new std::string("Hello world"));

SmartString ss2 = ss;

//Test af copy constructor

std::cout << "Test af copy constructor" << std::endl;

SmartString ss3(ss);

std::cout << "Destructor call ss3 " << std::endl; ss3.~SmartString;

std::cout << "Destructor call ss2 " << std::endl; ss2.~SmartString;

//Test af destructor

std::cout << "Test af destructor" << std::endl; std::cout << "str_ inden delete:" << std::endl;

std::cout << "Destructor call ss and now the destuctor should delete counter_ and str_ " << std::endl; ss.~SmartString; }

code

=Exercise 4 Discarding our solution in favor of boost::shared ptr<>= During the dierent exercises we have embarked on a journey where each and every step improves/enhances our previous solution. Other than that we have gained a better understanding of the language that we utilize.

In Exercise 3 we succeeded in creating a viable solution that in reality would improve our programs by making them less error-prone. However instead of reinventing the wheel, we will make a rather large jump and start using the boost library, in particular we will be using boost::shared ptr<>.

Exercise 4.1 Using boost::shared ptr<>
The template class boost::shared ptr<> incorporates the dierent aspects that we have covered and then some.

Use the boost::shared ptr<> and get to know it. Utilize the dierent test harnesses that you have concocted and create a new one that veri es that boost::shared ptr<> works as intended, and that it can be used in the use-cases discussed above.

As stated earlier the test harnesses must be presented on your wikis.

code format="cpp"
 * 1) include 
 * 2) include

int main(int argc, char* argv[]) {       //Make a boost boost::shared_ptr ss(new std::string("Hello world"));

std::cout << "Test af contructor:" << std::endl << std::endl;

std::cout << "counter_ er: " << ss.use_count<< std::endl;

if(ss->find("world")!=std::string::npos) {       std::cout << "The 'ss' string does contain 'world'"< ss2 = ss; // <- Deliberately why? What happens?

std::cout << "counter_ er: " << ss2.use_count<< std::endl;

if(ss2->find("world")!=std::string::npos) {       std::cout << "The 'ss2' string does contain 'world'"< ss3(ss2);

std::cout << "counter_ er: " << ss3.use_count<< std::endl; if(ss3->find("world")!=std::string::npos) {       std::cout << "The 'ss3' string does contain 'world'"<<std::endl; }   else std::cout << "The 'ss3' string does NOT contain 'world'" << std::endl; }   std::cout << "The 'ss3' should now be deleted" << std::endl; std::cout << "counter_ er: " << ss.use_count<< std::endl; } } code

=Exercise 5 Resource Handling= Perspective of this particular exercises:
 * What do you consider a resource?
 * //CPU//
 * //Thread priority//
 * //MemoryHarddisc//
 * RAM
 * Cache
 * //File Handling//
 * //Sockets//
 * In which situations do you foresee challenges with resources and how could they be handled?
 * //A computer is physically limited by memory and CPU, you can allocate resources when you need them and deallokere them when not in use anymore, to improve the performance of a computer.//
 * In particular regarding memory, when would you be able eliminate the need for allocations. Or when is it a must that something is allocated(on heap)?
 * //Sometimes there is trouble to dealokeret. And in very large programs can be difficult to overview the code, the smart pointer help tp dealkoere in scope end.//
 * //Sometimes there is trouble to dealokeret. And in very large programs can be difficult to overview the code, the smart pointer help tp dealkoere in scope end.//