I3ISU - Exercise 9: Resource Handling

Introduction
The purpose of this exercise is to get acquainted with different design idioms that are used to keep track of resources and makes sure the resources are relinquished when they are no longer needed.

Exercise Description
The task in subexercise 1 is to combine RAII and the SmartPointer idiom 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. The idea comes from the following: In a situation where dynamically allocated resources are a necessity, a garbage collected approach which incorporates pointer like semantics is desired The following UML class SmartString should be implemented and then tested with the provided code snippet from the exercise description:



The implemented "SmartString"
SmartString.hpp: SmartString.cpp:

The provided code snippet for testing SmartString
main.cpp:

Questions to answer
The class SmartString holds a pointer to a std::string object. Using the default copy constructor or assignment operator would mean you could have to objects with a pointer pointing to the same object. When the destructor of one of these objects are called then it will attempt to delete the pointer meaning freeing the memory holding the object. The pointer in the remaining object will now point to a part of memory with no valid object.
 * Why must the copy constructor and assignment operator be private with no implementation? And what is the consequence when these are private?

It returns the pointer to the string object, meaning that we have access to the members of the string object. This means that the SmartString now has pointer properties and that using the operator -> gives direct access to the members of the string object, as if the SmartString was itself the pointer.
 * What exactly does the operator-> do?

Exercise Description
In this exercise "SmartString" is extended, such that multiple parties may have a reference to it. This means that the assignment operator and copy constructormust be public and have an implementation. The UML class SmartString to implement:



The implemented SmartString
SmartString.hpp:

SmartString.cpp:

Testing the SmartString
Testing the implemented SmartString was done using CppUTest www.cpputest.org: CppUTest is a C /C++ based unit xUnit test framework for unit testing and for test-driving your code CppUTest reports memory leaks in the following way: CppUTest has memory leak detection support on a per-test level. This means that it automatically checks whether the memory at the end of a test is the same as at the beginning of the test. The test group for testing SmartString:

TG_CounterPointer.cpp Running the test compiling AllTests.cpp compiling TG_CountedPointer.cpp compiling i3isu_ex9_sub2BuildTimeTest.cpp compiling main.cpp compiling SmartString.cpp compiling i3isu_ex9_sub2BuildTime.cpp Building archive lib/libi3isu_ex9_sub2.a ar: creating lib/libi3isu_ex9_sub2.a a - objs/src/main.o a - objs/src/SmartString.o a - objs/src/util/i3isu_ex9_sub2BuildTime.o Linking i3isu_ex9_sub2_tests cc -g  -o i3isu_ex9_sub2_tests objs/tests/AllTests.o objs/tests/TG_CountedPointer.o objs/tests/util/i3isu_ex9_sub2BuildTimeTest.o lib/libi3isu_ex9_sub2.a ../cpputest/lib/libCppUTest.a -lstdc++ Running i3isu_ex9_sub2_tests TEST(i3isu_ex9_sub2BuildTime, Create) - 0 ms TEST(TG_SmartString, assignment_operator) - 0 ms TEST(TG_SmartString, CONSTRUCTOR_copy) - 0 ms TEST(TG_SmartString, OPERATOR_dereference) - 0 ms TEST(TG_SmartString, OPERATOR_pointer_to_member) - 0 ms TEST(TG_SmartString, CONSTRUCTOR_initial) - 0 ms

OK (6 tests, 6 ran, 24 checks, 0 ignored, 0 filtered out, 1 ms)

Questions to answer
The counter must be dynamically allocated for eeach object created of the type SmartString. The allocation should happen in the constructor when creating a new SmartString. I The copy constructor initializes the new SmartString to have it's counter pointer and string pointer point to the string and counter in the existing object. It then increments the counter to make sure that the destructor of each object knows not to delete these to pointers when more references still exist. First it a check is done to see if the SmartString is assigned to itself. If it is assigned to itself nothing further is done. If it is being assigned to another object then the counter will first be decremented and then set to point to the counter in the object being assigned and incremented. If an object is assigned another object which already points to the same string, then the result will be both decrementing and incrementing the counter, meaning that the counter is left having the same value as before the assignment. If it is being assigned an object which points to another string than itself, then the counter in the object it was previously assigned will be decremented and the counter in the new assigned object will be incremented. In the constructor the counter is decremented. If no other references exist to the string pointed to by the object, then both the string and the counter is freed.
 * Why must the counter be dynamically allocated? Where should this happen?
 * How is the copy constructor implemented?
 * How is the assignment operator implemented?
 * What happens in the destructor and how should it be implemented?

Subexercise 3: Templated Counted Smart Pointer (OPTIONAL)
Skipped!

Subexercise 4: Discarding our solution in favor of boost::shared_ptr<>
"Subexercise 4.1: Using boost::shared_ptr<>" is done here. "Exercise 4.2: Messages wrapped in a boost::shared_ptr<>" is optional and skipped here.

Exercise Description
The purpose of subexercise 4 is to show that the boost library can be used in place of the previously created SmartString. This is to avoid reinventing the wheel. The exercise will show that boost::shared_ptr has the functionality we were looking for in subexercise 2.

Exercise Solution
To show that boost::shared_ptr can be used in place of SmartString, it is enough to show that it passes the tests from subexercise 2 modified for using boost::shared_ptr.

TG_boost_shared_ptr.cpp Running the test compiling TG_boost_shared_ptr.cpp Linking i3isu_ex9_sub2_tests cc -g  -o i3isu_ex9_sub2_tests objs/tests/AllTests.o objs/tests/TG_boost_shared_ptr.o objs/tests/util/i3isu_ex9_sub4BuildTimeTest.o lib/libi3isu_ex9_sub2.a ../cpputest/lib/libCppUTest.a -lstdc++ Running i3isu_ex9_sub2_tests TEST(i3isu_ex9_sub4BuildTime, Create) - 0 ms TEST(TG_boost_shared_ptr, assignment_operator) - 0 ms TEST(TG_boost_shared_ptr, CONSTRUCTOR_copy) - 0 ms TEST(TG_boost_shared_ptr, OPERATOR_dereference) - 0 ms TEST(TG_boost_shared_ptr, OPERATOR_pointer_to_member) - 0 ms TEST(TG_boost_shared_ptr, Constructor_initial) - 0 ms

OK (6 tests, 6 ran, 20 checks, 0 ignored, 0 filtered out, 0 ms)

Subexercise 5: Resource Handling
This subexercise only contains perspectives the exercise, with given questions being answered. A resource is data in memory or some property or mechanism residing in memory which are used by a number of objects or initiators. Examples could be sharing a mutex, conditional or just some data in memory between objects or threads. A problem is that deallocation of resources is not always foolproof. Methods like the ones shown in this exercise like using RAII and smart pointers can solve some of these problems. Or when is it a must that something is allocated (on heap)? If there is dependencies to a resource from several sources, and when it is not needed to modify the data after creatiion, then only a reference is needed. If a copy is needed, so that both the original resource and the copy can be modified independently, then it is a must that it is allocated on heap.
 * What do you consider a resource?
 * In which situations do you foresee challenges with resources and how could they be handled?
 * In particular regarding memory, when would you be able to eliminate the need for allocations.