I need to process a large number of items. To do this, a resource is required which in this case is an external software program.
Due to memory leaks of the external software it is not possible to process all items with a single instance of the resource. Creating a new instance of the resource is not an option for performance reasons. Therefore I need to process the items in portions of a given size N. This means I create an instance of the resource, process the next N items, then deallocate the resource. This process is repeated until all items have been processed.
Processing of an item is actually a complicated process which can cause different types of failures (exceptions). Therefore I like to use the RAII idiom to manage the resource and make sure each instance is cleanly deallocated.
It is no big deal to implement this with two nested loops as in this example:
#include <iostream>
#include <vector>
class ResourceAllocator {
public:
ResourceAllocator() { std::cout << "Allocating resource\n"; }
~ResourceAllocator() { std::cout << "Deallocating resource\n"; }
void Process(int n) { std::cout << "Processing item " << n << "\n"; }
};
int main()
{
const int totalSize = 20;
const int portionSize = 6;
std::vector<int> items(totalSize);
int count = 0;
bool complete = false;
while (!complete) {
ResourceAllocator a;
for (int i = 0; i < portionSize; i++) {
a.Process(items[i]);
count++;
if (count >= totalSize) {
complete = true;
break;
}
}
}
}
However I keep wondering if there is a solution that requires only a single loop.
I create an instance of the resource, process the next N items, then deallocate the resource. This process is repeated until all items have been processed.
You can use move semantics for transferring the ownership of a resource. When an object following the RAII idiom is the target of a move assignment, it releases the resource it owns (if any) and takes ownership of the resource being assigned to it – the source of the assignment operation:
Resource r(/* 1st resource */);
// ...
r = Resource(/* 2nd resource */);
The assignment should release the resource r
owns and obtain the ownership of the new resource being created (i.e., Resource(/* 2nd resource */)
).
You should implement a move assignment operator for your class. When the objects have been processed, you use these objects as the targets of move assignment.