1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
#include <iostream>
#include <functional>
#include <map>
#include <vector>
// first: a unique handler number to identify this handler, second: handler function
using interrupt_handler_t = std::pair< unsigned int, std::function< void() > > ;
// key == interrupt number, mapped data == vector of interrupt handlers
using handler_map_t = std::map< unsigned int, std::vector<interrupt_handler_t> > ;
// return unique handler number of the added handler
unsigned int add_handler( handler_map_t& handler_map, unsigned int interrupt_number, std::function< void() > handler )
{
static unsigned int handler_id = 0 ; // unique ids for the handlers
handler_map[interrupt_number].emplace_back( ++handler_id, std::move(handler) ) ; // increment handler_id for each handler
return handler_id ;
}
// remove handler with this unique handler number, return true on success
bool remove_handler( handler_map_t& handler_map, unsigned int unique_handler_number )
{
for( auto&[ int_num, vec ] : handler_map )
for( auto iter = vec.begin() ; iter != vec.end() ; ++iter )
if( iter->first == unique_handler_number )
{
vec.erase(iter) ;
return true ;
}
return false ; // no handler with this unique_handler_number
}
// return number of handlers called
std::size_t try_handle_interrupt( unsigned int interrupt_number, const handler_map_t& handler_map )
{
const auto iter = handler_map.find(interrupt_number) ;
if( iter != handler_map.end() ) // if an entry is found
{
// call the handlers stored in the vector
for( auto& handler : iter->second ) handler.second() ;
return iter->second.size() ; // number of handlers
}
else return 0 ;
}
int main()
{
struct A
{
void handle_interrupt_1() { std::cout << "A::handler for interrupt #1 A object: " << this << '\n' ; }
void handle_interrupt_2() { std::cout << "A::handler for interrupt #2 A object: " << this << '\n' ; }
};
struct B
{
void handle_interrupt_1() { std::cout << "B::handler for interrupt #1 B object: " << this << '\n' ; }
void handle_interrupt_2( int extra_arg )
{ std::cout << "B::handler for interrupt #2 B object: " << this << " extra_arg: " << extra_arg << '\n' ; }
};
A a1, a2 ;
B b ;
handler_map_t handler_map ;
// add handlers for interrupt #1
[[maybe_unused]] const auto h11 = add_handler( handler_map, 1, std::bind( &A::handle_interrupt_1, std::ref(a1) ) ) ;
const auto h12 = add_handler( handler_map, 1, std::bind( &B::handle_interrupt_1, std::ref(b) ) ) ;
// add handlers for interrupt #2
[[maybe_unused]] const auto h21 = add_handler( handler_map, 2, std::bind( &A::handle_interrupt_2, std::ref(a1) ) ) ;
const auto h22 = add_handler( handler_map, 2, std::bind( &A::handle_interrupt_2, std::ref(a2) ) ) ;
const auto h23 = add_handler( handler_map, 2, std::bind( &B::handle_interrupt_2, std::ref(b), 23 /* pass 23 as extra_arg */ ) ) ;
std::cout << "\n*** added five handlers ***\n\n" ;
// try handling some interrupts
for( unsigned int interrupt_number = 1 ; interrupt_number < 4 ; ++interrupt_number )
{
std::cout << "interrupt_number #" << interrupt_number << '\n' ;
if( const auto n = try_handle_interrupt( interrupt_number, handler_map ) )
std::cout << "handled: " << n << " handlers were called\n" ;
else std::cout << "unhandled: no entry in the map for this interrupt in the map\n" ;
std::cout << "\n---------------------------\n" ;
}
// remove some handlers
remove_handler( handler_map, h12 ) ;
remove_handler( handler_map, h22 ) ;
remove_handler( handler_map, h23 ) ;
std::cout << "\n*** removed three of the handlers ***\n\n" ;
// and try handling the interrupts again
for( unsigned int interrupt_number = 1 ; interrupt_number < 4 ; ++interrupt_number )
{
std::cout << "interrupt_number #" << interrupt_number << '\n' ;
if( const auto n = try_handle_interrupt( interrupt_number, handler_map ) )
std::cout << "handled: " << n << " handlers were called\n" ;
else std::cout << "unhandled: no entry in the map for this interrupt in the map\n" ;
std::cout << "\n---------------------------\n" ;
}
}
|