Skip to content

Instantly share code, notes, and snippets.

@sansuiso
Created March 25, 2015 17:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sansuiso/f764aff7bb176e739ce3 to your computer and use it in GitHub Desktop.
Save sansuiso/f764aff7bb176e739ce3 to your computer and use it in GitHub Desktop.
Concurrency bug (and solution)
#include <iostream>
#include <vector>
#include <memory>
#include <thread>
class Base
{
public:
/**
* Public interface to a complex algorithm.
*
* The complex algorithm can have variants (e.g.,
* put the data in the correct shape, apply some
* post-processing to remove outliers in the result...).
* The virtual methdos are private so that clients of the class
* do only see a stable interface and the sequence of execution
* does also remain stable.
*
* The outline of the algorithm is always:
* 1. pre-processing step (can be overriden)
* 2. processing (fixed)
* 3. result post-processing (can be overriden)
*/
void performComplexAlgorithm() const
{
preprocessing();
processing();
postprocessing();
}
private:
/**
* Prepare the data (e.g., convert RGB images to GRAY).
* Can be overriden by subclasses.
*/
virtual void preprocessing() const
{
std::cout << "Base::" << __FUNCTION__ << std::endl;
}
/**
* Really solve the problem here.
*/
void processing() const
{
std::cout << "Base::" << __FUNCTION__ << std::endl;
}
/**
* Post-process the data (remove outliers, put back to RGB...).
* Can be overriden by subclasses.
*/
virtual void postprocessing() const
{
std::cout << "Base::" << __FUNCTION__ << std::endl;
}
};
/**
* Specialized class to deal with a certain type of data
*/
class Derived : public Base
{
private:
/**
* This special type of data needs to be put into a usable shape
* for our brilliant processing function.
*/
virtual void preprocessing() const override
{
std::cout << "Derived::" << __FUNCTION__ << std::endl;
}
};
void wrongWorker(Base const solver)
{
std::cout << "Inside " << __FUNCTION__ << std::endl;
solver.performComplexAlgorithm();
}
void correctWorker(Base const& solver)
{
std::cout << "Inside " << __FUNCTION__ << std::endl;
solver.performComplexAlgorithm();
}
int main()
{
std::cout << "Sanity check: call performComplexAlgorithm from Derived:" << std::endl;
Derived D0;
D0.performComplexAlgorithm();
std::cout << std::endl;
std::unique_ptr<Base> D1 = std::unique_ptr<Derived>(new Derived);
std::cout << "Polymorphic access via a pointer:" << std::endl;
D1->performComplexAlgorithm();
std::cout << std::endl;
std::cout << "Wrong (calls methods from the BASE class):" << std::endl;
wrongWorker(*D1);
std::cout << std::endl;
std::cout << "Correct (calls methods from the DERIVED class):" << std::endl;
correctWorker(*D1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment