Tuesday, October 14, 2014

realization of callback in cpp

main.cpp
#include <iostream>
#include <list>
#include <string>

using std::list;
using std::string;
using std::cout;
using std::endl;

#define callback_macro(facade, call) \
 \
for(list<transactor_callbacks*>::iterator it=this->callbacks.begin(); it!=this->callbacks.end(); ++it) { \
   facade* cb = dynamic_cast<facade*>(*it); \
   cb->call; \
}

class transactor_callbacks {
public:
    virtual ~transactor_callbacks(){}
};

class driver;
class driver_callbacks: virtual public transactor_callbacks {
public:
   virtual void driver_pre_transactor (driver* xactor, bool* drop) {}
   virtual void driver_post_transactor (driver* xactor) {}

};

class driver {
public:
    virtual bool prepend_callback(transactor_callbacks* cb) {
        for(list<transactor_callbacks*>::iterator it=callbacks.begin(); it!=callbacks.end(); ++it) {
            if(cb == *it) {
                return 1;
            }
        }

        callbacks.push_front(cb);

        return 0;
    }

    virtual bool append_callback(transactor_callbacks* cb) {
        for(list<transactor_callbacks*>::iterator it=callbacks.begin(); it!=callbacks.end(); ++it) {
            if(cb == *it) {
                return 1;
            }
        }

        callbacks.push_back(cb);

        return 0;
    }

    virtual bool unregister_callback(transactor_callbacks* cb) {
        for(list<transactor_callbacks*>::iterator it=callbacks.begin(); it!=callbacks.end(); ++it) {
            if(cb == *it) {
                callbacks.erase(it);
                return 0;
            }
        }

        return 1;
    }

    void run() {
        callback_macro(driver_callbacks, driver_pre_transactor(this, &drop));
        callback_macro(driver_callbacks, driver_post_transactor(this));
    }

    list<transactor_callbacks*> callbacks;
    bool drop;
};

class driver_pre_transactor1: public driver_callbacks {
public:
    driver_pre_transactor1(string name="cb1"):driver_callbacks() {
        this->name = name;
    }

   virtual void driver_pre_transactor (driver* xactor, bool* drop) {
       cout << name << ": before transactor" << endl;
   }

private:
    string name;

};

class driver_post_transactor2: public driver_callbacks {
public:
    driver_post_transactor2(string name="cb2"):driver_callbacks() {
        this->name = name;
    }

    virtual void driver_post_transactor (driver* xactor) {
        cout << name << ": after transactor" << endl;
    }

private:
    string name;

};

int main(int argc, char** argv) {
    driver* drv = new driver();
    driver_pre_transactor1* drv_pre_tx1 = new driver_pre_transactor1("pre_tx1");
    driver_pre_transactor1* drv_pre_tx2 = new driver_pre_transactor1("pre_tx2");
    driver_post_transactor2* drv_post_tx1 = new driver_post_transactor2("post_tx1");

    drv->append_callback(drv_pre_tx1);
    drv->append_callback(drv_pre_tx2);
    drv->append_callback(drv_post_tx1);
    drv->run();

    drv->unregister_callback(drv_pre_tx2);
    drv->run();

    return 0;
}

Makefile
PROJECT = main
EXE = $(PROJECT).exe

OBJ = $(patsubst %.exe,%.o,$(EXE))

.PHONY: clean all

all: clean $(EXE)

clean:
rm -rf *.o *.exe

$(EXE): $(OBJ)
g++ $^ -o $@

No comments:

Post a Comment