Информация об изменениях

Сообщение Re[4]: Как такое написать по Сиплюсплюсному? от 24.03.2025 9:08

Изменено 24.03.2025 10:56 kov_serg

Re[4]: Как такое написать по Сиплюсплюсному?
Здравствуйте, B0FEE664, Вы писали:

BFE>Тупое решение "в лоб":

Дык хотелось не заводить лишних указателей.

BFE>А зачем так издеваться над объектно ориентированным подходом?

Очень просто это указатель группу функци — переходник такой.

Идея примерно такая:
struct Listner {
    virtual void begin(void *args)=0;
    virtual int  progress(double p)=0;
    virtual void end(void *res)=0;
};
struct Worker { /*...*/ }; // постепенно исполняемая функция, иногда требующая осязаемого времени на выполнение
struct Workers { /*...*/ }; // выполняет постепенно исполняемые функции в разных потоках, полю имеет очереть сообщений для коммуникации и сигналы для аварийной связи
struct Action1Args { string query; };
struct Action1Result { string result; };
struct Action1Worker : Worker { /*...*/ }; // например db query
struct Action2Args { int a,b; };
struct Action2Result { int c,f; };
struct Action2Worker : Worker { /*...*/ }; // или какой-нибудь https request

struct GUIWindow {
    struct:Listner {
        GUIWindow* parent() { return parent_of(this,&GUIWindow::action1); }
        void begin(void *args) { parent()->action1_begin((Action1Args*)args); }
        int  progress(double p) { return parent()->action1_progress(p); }
        void end(void *res) { parent()->action1_end((Action2Result*)res); }
    } action1[1];
    struct:Listner {
        GUIWindow* parent() { return parent_of(this,&GUIWindow::action2); }
        void begin(void *args) { parent()->action2_begin((Action2Args*)args); }
        int  progress(double p) { return 0; }
        void end(void *res) { parent()->action2_end((Action2Result*)res); }
    } action2[1];
    Workers workers[1];
    Action1Worker a1w[1];
    Action2Worker a2w[1];
    enum { action1_id,action2_id };
    void init() {
        workers->set(action1_id,action1,a1w); // что-бы тут не передавать кучу функций
        workers->set(action2_id,action2,a2w); // или не делать одну но с длинным switch и кучей event codes
    };
    void done() {
        workers->done();
    }
    // ...
    void on_action1() { workers->start(action1_id); }
    void on_action1_cancel() { workers->cancel(action1_id); }
    void on_action2() { workers->start(action2_id); }
    void on_action2_cancel() { workers->cancel(action2_id); }
    void on_msg_loop() { workers->msg_loop(); } // тут собственно диспечеризируем сообщения по функциям (в основном потоке)
    // ...
    void enable_action1(bool en) {
        btn_action1.Enable(en);
        btn_action1_cancel.Enable(!en);
        progress.Show(!en);
    }
    void action1_begin(Action1Args *args) {
        args->query=edQuery.Text;
        enable_action1(false);
    }
    int action1_progress(double p) {
        action1_progress.SetProgess(p);
        return 0;
    }
    void action1_end(Action1Result *res) {
        edResult.SetText(res->result);
        enable_action1(true);
    }
    void action2_begin(Action2Args *args) {
        args->a=10;
        args->b=22;
        action2_spinner.Active(true);
    }
    void action2_end(Action2Result *res) {
        lbResult=fmt("result=%d",res->c);
        action2_spinner.Active(false);
    }
    //...
};
Re[4]: Как такое написать по Сиплюсплюсному?
Здравствуйте, B0FEE664, Вы писали:

BFE>Тупое решение "в лоб":

Дык хотелось не заводить лишних указателей.

BFE>А зачем так издеваться над объектно ориентированным подходом?

Очень просто это указатель группу функций — переходник такой.

Идея примерно такая:
struct Listner {
    virtual void begin(void *args)=0;
    virtual int  progress(double p)=0;
    virtual void end(void *res)=0;
};
struct Worker { /*...*/ }; // постепенно исполняемая функция, иногда требующая осязаемого времени на выполнение
struct Workers { /*...*/ }; // выполняет постепенно исполняемые функции в разных потоках, полю имеет очереть сообщений для коммуникации и сигналы для аварийной связи
struct Action1Args { string query; };
struct Action1Result { string result; };
struct Action1Worker : Worker { /*...*/ }; // например db query
struct Action2Args { int a,b; };
struct Action2Result { int c,f; };
struct Action2Worker : Worker { /*...*/ }; // или какой-нибудь https request

struct GUIWindow {
    struct:Listner {
        GUIWindow* parent() { return parent_of(this,&GUIWindow::action1); }
        void begin(void *args) { parent()->action1_begin((Action1Args*)args); }
        int  progress(double p) { return parent()->action1_progress(p); }
        void end(void *res) { parent()->action1_end((Action2Result*)res); }
    } action1[1];
    struct:Listner {
        GUIWindow* parent() { return parent_of(this,&GUIWindow::action2); }
        void begin(void *args) { parent()->action2_begin((Action2Args*)args); }
        int  progress(double p) { return 0; }
        void end(void *res) { parent()->action2_end((Action2Result*)res); }
    } action2[1];
    Workers workers[1];
    Action1Worker a1w[1];
    Action2Worker a2w[1];
    enum { action1_id,action2_id };
    void init() {
        workers->set(action1_id,action1,a1w); // что-бы тут не передавать кучу функций
        workers->set(action2_id,action2,a2w); // или не делать одну но с длинным switch и кучей event codes
    };
    void done() {
        workers->done();
    }
    // ...
    void on_action1() { workers->start(action1_id); }
    void on_action1_cancel() { workers->cancel(action1_id); }
    void on_action2() { workers->start(action2_id); }
    void on_action2_cancel() { workers->cancel(action2_id); }
    void on_msg_loop() { workers->msg_loop(); } // тут собственно диспечеризируем сообщения по функциям (в основном потоке)
    // ...
    void enable_action1(bool en) {
        btn_action1.Enable(en);
        btn_action1_cancel.Enable(!en);
        progress.Show(!en);
    }
    void action1_begin(Action1Args *args) {
        args->query=edQuery.Text;
        enable_action1(false);
    }
    int action1_progress(double p) {
        action1_progress.SetProgess(p);
        return 0;
    }
    void action1_end(Action1Result *res) {
        edResult.SetText(res->result);
        enable_action1(true);
    }
    void action2_begin(Action2Args *args) {
        args->a=10;
        args->b=22;
        action2_spinner.Active(true);
    }
    void action2_end(Action2Result *res) {
        lbResult=fmt("result=%d",res->c);
        action2_spinner.Active(false);
    }
    //...
};