Created
December 22, 2011 10:54
-
-
Save StonedXander/1509910 to your computer and use it in GitHub Desktop.
Simple Consumer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Consumer generic class. | |
* Delegates the following services: | |
* - evaluate : returns if the run method must be exited. | |
* - process : process the item buffer. | |
* - compute : compute the internal state. | |
* The 'target' concept must implement the method: | |
* bool swap(I **, unsigned *); | |
* and the constructor : | |
* T::T(K *); | |
* Hence, delegate and target shares the same initialisation context. | |
* It provides a working buffer. | |
*/ | |
template <typename T, typename I, typename D, typename K> class Consumer { | |
public: | |
/** | |
* Constructor. | |
*/ | |
Consumer(K *context) : delegate(context), target(context), buffer(0), size(0) {} | |
/** | |
* Entry point. | |
*/ | |
void run() { | |
while(delegate.evaluate()) { | |
if(target.swap(&buffer, &size)) { | |
delegate.process(buffer, size); | |
} | |
delegate.compute(); | |
} | |
} | |
private: | |
D delegate; | |
T target; | |
I *buffer; | |
unsigned int size; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Here is the provider class, maintaining the double buffered list. | |
* By the way, it will also need a delegation object, taking the exact | |
* same context in constructor parameters. | |
*/ | |
template <typename I, typename K> class Provider { | |
public: | |
/** | |
* Constructor. | |
* The context strikes back, but it's stronger now ! | |
*/ | |
Provider(K *context) { | |
// Guess who will have a parametrized method which the following prototype ? | |
// template <typename I> void initialize(I **buffer); | |
context->initialize(&buffer); | |
context->initialize(&unused); | |
size = 0; | |
// TODO Initialize mutexes | |
} | |
bool swap(I **bf, unsigned int *sz) { | |
bool result = size != 0; // Not thread safe. In fact, it's not a problem. | |
// If we miss it now, we'll catch it later. It just implies a silent latency. | |
if(result) { // Grrr ... Branches ... | |
lock(); // Mutex call. | |
*bf = buffer; | |
*sz = size; | |
size = 0; | |
buffer = unused; | |
unused = *bf; | |
unlock(); // Mutex call. | |
} | |
return result; | |
} | |
private: | |
I *buffer; | |
I *unused; | |
unsigned int size; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
By now, thre's an obvious spot of optimisation. Run method calls four methods !! 'evaluate' can be inlined. There's two branches. Now, everything will depend on the target. If it's well implemented, we can expected a tail-call optimisation. It will be interesting to check generated assembly.