c++ handle模式

struct MessageBase {
    virtual ~MessageBase() {}
};

template<typename Msg>
class MessageWrapper : public MessageBase {
private:
    Msg msg;
public:
    explicit MessageWrapper(const Msg &msg) : msg(msg) {}
};


class Queue {
private:
    queue<shared_ptr<MessageBase>> q;
    mutex mu;
    condition_variable con;
public:
    Queue() = default;

    template<typename Msg>
    void push(const Msg msg) {
        lock_guard<mutex> lk(mu);
        q.push(make_shared<MessageWrapper<Msg>>(msg));
        con.notify_all();
    }

    shared_ptr<MessageBase> wait_and_pop() {
        unique_lock<mutex> lk(mu);
        con.wait(lk, [this]() {
            return !q.empty();
        });
        shared_ptr<MessageBase> ret = q.front();
        q.pop();
        return ret;
    }
};

template<typename PreDispatcher, typename Msg, typename Func>
class TemplateDispatcher {
private:
    Queue *q;
    PreDispatcher *pre = nullptr;
    bool chained = false;
    Func func;

    template<typename OtherTemplateDisPatcher, typename OtherMsg, typename OtherFunc>
    friend
    class TemplateDispatcher;

    void wait_and_dispatch() {
        for (;;) {
            auto res = q->wait_and_pop();
            if (dispatch(res)) {
                break;
            }
        }
    }

     TemplateDispatcher(const TemplateDispatcher &) = delete;

    TemplateDispatcher &operator=(const TemplateDispatcher &) = delete;

public:
    TemplateDispatcher(Queue *q, PreDispatcher *pre, Func &&f) : q(q), pre(pre), func(forward<Func>(f)),
                                                                 chained(false) {
        pre->chained = true;
    }

     TemplateDispatcher(TemplateDispatcher &&other)  noexcept : q(other.q), pre(other.pre), func(move(other.func)),
                                                     chained(other.chained) {
        other.chained = true;
    }

    template<class OtherMsg, typename OtherFunc>
    TemplateDispatcher<TemplateDispatcher, OtherMsg, OtherFunc> handle(OtherFunc &&otherFunc) {
        return TemplateDispatcher<TemplateDispatcher, OtherMsg, OtherFunc>(q, this, forward<OtherFunc>(otherFunc));
    }

    bool dispatch(shared_ptr<MessageBase> msg) {
        auto inner = dynamic_cast<MessageWrapper<Msg> *>(msg.get());
        if (inner) {
            func();
            return true;
        }
        return pre->dispatch(msg);
    }

    ~TemplateDispatcher() noexcept(false) {
        if (!chained) {
            wait_and_dispatch();
        }
    }
};

struct CloseQueue {
};

class Dispatcher {
private:
    Queue *q;
    bool chained;

    template<typename Dispatcher, typename Msg, typename Func>
    friend
    class TemplateDispatcher;

    [[noreturn]] void wait_and_dispatch() {
        for (;;) {
            auto res = q->wait_and_pop();
            dispatch(res);
        }
    }

    Dispatcher(const Dispatcher &) = delete;

    Dispatcher &operator=(const Dispatcher &) = delete;

public:
    explicit Dispatcher(Queue *q) : q(q), chained(false) {}

    Dispatcher(Dispatcher &&other)  noexcept : q(other.q), chained(other.chained) {
        other.chained = true;
    }

    template<class Msg, typename Func>
    TemplateDispatcher<Dispatcher, Msg, Func> handle(Func &&func) {
        return TemplateDispatcher<Dispatcher, Msg, Func>(this->q, this, forward<Func>(func));
    }

    static bool dispatch(shared_ptr<MessageBase> msg) {
        auto inner = dynamic_cast<MessageWrapper<CloseQueue> *>(msg.get());
        if (inner) {
            throw new CloseQueue{};
        }
        return false;
    }

    ~Dispatcher() noexcept(false) {
        if (!chained) {
            wait_and_dispatch();
        }
    }
};


class Receiver {
public:
    Queue q;
public:
    Receiver() {}

    Dispatcher wait() {
        return Dispatcher(&q);
    }
};

struct One {
};
struct Two {
};

class Three {
};

int main() {
    Receiver incoming;
    thread producer([&]() {
        srand(time(NULL));
        while(true) {
            int t = random() % 100;
            if (t < 30) {
                incoming.q.push(One{});
            } else if (t < 60) {
                incoming.q.push(Two{});
            } else if (t < 95) {
                incoming.q.push(Three{});
            } else {
                incoming.q.push(CloseQueue{});
                break;
            }
            this_thread::sleep_for(chrono::seconds(1));
        }
    });
    for (;;) {
        try {
            incoming.wait().handle<One>([&]() {
                cout << "One" << endl;
            }).handle<Two>([&]() {
                cout << "Two" << endl;
            }).handle<Three>([&](){
                cout << "Three" << endl;
            });
        } catch (CloseQueue *cq) {
            cout << "catch" << endl;
            break;
        }
    }
    producer.join();
}

你可能感兴趣的:(c++,算法,开发语言)