Last active
August 3, 2017 14:04
-
-
Save pan-/b136a3d56200c0f1647d43d1315ed427 to your computer and use it in GitHub Desktop.
static instrumentation framework
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
class BlockDeviceInstrumentCounter : public DefaultBlockDeviceInstrument { | |
public: | |
BlockDeviceInstrumentCounter() : counter(0) { } | |
void reset() { | |
counter = 0; | |
} | |
size_t get_counter() const { | |
return counter; | |
} | |
protected: | |
size_t counter; | |
}; |
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
template<typename Base, typename Discriminator> | |
struct Leaf : public Base { }; | |
template< | |
typename Instrument1, | |
typename Instrument2 | |
> | |
struct CompositeBlockDeviceInstrument : | |
public Leaf< | |
Instrument1, CompositeBlockDeviceInstrument<Instrument1, Instrument2> | |
>, | |
public Leaf< | |
Instrument2, CompositeBlockDeviceInstrument<Instrument1, Instrument2> | |
> { | |
typedef Leaf<Instrument1, CompositeBlockDeviceInstrument<Instrument1, Instrument2> > I1; | |
typedef Leaf<Instrument2, CompositeBlockDeviceInstrument<Instrument1, Instrument2> > I2; | |
CompositeBlockDeviceInstrument() : I1(), I2() { } | |
void before_read(void *buffer, bd_addr_t addr, bd_size_t size) { | |
I1::before_read(buffer, addr, size); | |
I2::before_read(buffer, addr, size); | |
} | |
void after_read(int result, void *buffer, bd_addr_t addr, bd_size_t size) { | |
I1::after_read(result, buffer, addr, size); | |
I2::after_read(result, buffer, addr, size); | |
} | |
void before_program(const void *buffer, bd_addr_t addr, bd_size_t size) { | |
I1::before_program(buffer, addr, size); | |
I2::before_program(buffer, addr, size); | |
} | |
void after_program(int result, const void *buffer, bd_addr_t addr, bd_size_t size) { | |
I1::after_program(result, buffer, addr, size); | |
I2::after_program(result, buffer, addr, size); | |
} | |
void before_erase(bd_addr_t addr, bd_size_t size) { | |
I1::before_erase(addr, size); | |
I2::before_erase(addr, size); | |
} | |
void after_erase(int result, bd_addr_t addr, bd_size_t size) { | |
I1::after_erase(result, addr, size); | |
I2::after_erase(result, addr, size); | |
} | |
void reset() { | |
I1::reset(); | |
I2::reset(); | |
} | |
template<typename T> | |
T& as() { | |
return static_cast<T&>(*this); | |
} | |
}; |
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
struct DefaultBlockDeviceInstrument { | |
void before_read(void *buffer, bd_addr_t addr, bd_size_t size) { } | |
void after_read(int result, void *buffer, bd_addr_t addr, bd_size_t size) { } | |
void before_program(const void *buffer, bd_addr_t addr, bd_size_t size) { } | |
void after_program(int result, const void *buffer, bd_addr_t addr, bd_size_t size) { } | |
void before_erase(bd_addr_t addr, bd_size_t size) { } | |
void after_erase(int result, bd_addr_t addr, bd_size_t size) { } | |
void reset() { } | |
}; |
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
void foo(BlockDevice* block_device) { | |
{ | |
InstrumentedBlockDevice<BlockDeviceReadFaillureCounter> foo(block_device); | |
// do work | |
size_t faillures = foo.get_instrument().get_counter(); | |
} | |
{ | |
InstrumentedBlockDevice< | |
CompositeBlockDeviceInstrument< | |
BlockDeviceReadFaillureCounter, BlockDeviceReadCounter | |
> | |
> bar(block_device); | |
size_t read_faillure = bar.get_instrument().as<BlockDeviceReadFaillureCounter>().get_counter(); | |
size_t read_counter = bar.get_instrument().as<BlockDeviceReadCounter>().get_counter(); | |
} | |
{ | |
InstrumentedBlockDevice< | |
CompositeBlockDeviceInstrument< | |
BlockDeviceReadFaillureCounter, | |
CompositeBlockDeviceInstrument< | |
BlockDeviceReadCounter, BlockDeviceReadTimingCounter | |
> | |
> | |
> baz(block_device); | |
size_t read_faillure = bar.get_instrument().as<BlockDeviceReadFaillureCounter>().get_counter(); | |
size_t read_counter = bar.get_instrument().as<BlockDeviceReadCounter>().get_counter(); | |
size_t read_timing_counter = bar.get_instrument().as<BlockDeviceReadTimingCounter>().get_counter(); | |
} | |
} |
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
class BlockDeviceReadCounter : public BlockDeviceInstrumentCounter { | |
public: | |
void after_read(int result, void *buffer, bd_addr_t addr, bd_size_t size) { | |
if (result == 0) { | |
counter += size; | |
} | |
} | |
}; | |
class BlockDeviceReadFaillureCounter : public BlockDeviceInstrumentCounter { | |
public: | |
void after_read(int result, void *buffer, bd_addr_t addr, bd_size_t size) { | |
if (result != 0) { | |
++counter; | |
} | |
} | |
}; | |
class BlockDeviceReadTimingCounter : public BlockDeviceInstrumentCounter { | |
public: | |
void before_read(void *buffer, bd_addr_t addr, bd_size_t size) { | |
timer.reset(); | |
} | |
void after_read(int result, void *buffer, bd_addr_t addr, bd_size_t size) { | |
if (result != 0) { | |
counter += timer.read_ms(); | |
} | |
} | |
Timer timer; | |
}; |
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
template<typename Instrument> | |
class InstrumentedBlockDevice : public BlockDevice { | |
public: | |
InstrumentedBlockDevice(BlockDevice* device) : | |
_block_device(device), _instrument() { } | |
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size) { | |
_instrument.before_read(buffer, addr, size); | |
int result = _block_device->read(buffer, addr, size); | |
_instrument.after_read(result, buffer, addr, size); | |
return result; | |
} | |
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size) { | |
_instrument.before_program(buffer, addr, size); | |
int result = _block_device->program(buffer, addr, size); | |
_instrument.after_program(result, buffer, addr, size); | |
return result; | |
} | |
virtual int erase(bd_addr_t addr, bd_size_t size) { | |
_instrument.before_erase(addr, size); | |
int result = _block_device->erase(addr, size); | |
_instrument.after_erase(result, addr, size); | |
return result; | |
} | |
Instrument get_instrument() { | |
return _instrument; | |
} | |
private: | |
BlockDevice* _block_device; | |
Instrument _instrument; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment