summaryrefslogtreecommitdiff
path: root/includes/Main.h
blob: 1c902eccb9f4e8639cbefd0aa5a3609c52df3a38 (plain)
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#pragma once

#include <Exceptions.h>

namespace Balau {

class AtStart {
  protected:
      AtStart(int priority = 0);
    virtual void doStart() = 0;
  private:
    const int m_priority;
    AtStart * m_next;
    static AtStart * s_head;
    friend class Main;
};

class AtExit {
  protected:
      AtExit(int priority = 0);
    virtual void doExit() = 0;
  private:
    const int m_priority;
    AtExit * m_next;
    static AtExit * s_head;
    friend class Main;
};

class Exit : public GeneralException {
  public:
      Exit(int code = -1) : GeneralException(), m_code(code) { String s; s.set("Application exitting with code = %i", code); setMsg(s.strdup()); }
    int getCode() { return m_code; }
  private:
    int m_code;
};

};

#include <Printer.h>
#include <Task.h>
#include <TaskMan.h>

namespace Balau {

class MainTask : public Task {
  public:
      MainTask() : m_stopTaskManOnExit(true) { }
      virtual ~MainTask() { if (m_stopTaskManOnExit) TaskMan::stop(); }
    virtual const char * getName() { return "Main Task"; }
    virtual void Do();
    void stopTaskManOnExit(bool v) { m_stopTaskManOnExit = v; }
  private:
    bool m_stopTaskManOnExit;
};

class Main {
  public:
    enum Status {
        UNKNOWN = 0,
        STARTING,
        RUNNING,
        STOPPING,
        STOPPED,
    };
      Main() : m_status(UNKNOWN) { Assert(s_application == 0); s_application = this; }
    static Status status() { return s_application->m_status; }
    int bootstrap(int _argc, char ** _argv) {
        int r = 0;
        m_status = STARTING;

        argc = _argc;
        argv = _argv;
        enve = NULL;

        for (AtStart * ptr = AtStart::s_head; ptr; ptr = ptr->m_next)
            ptr->doStart();

        try {
            m_status = RUNNING;
            MainTask * mainTask = createTask(new MainTask());
            TaskMan::getDefaultTaskMan()->mainLoop();
            m_status = STOPPING;
        }
        catch (Exit e) {
            m_status = STOPPING;
            r = e.getCode();
        }
        catch (GeneralException e) {
            m_status = STOPPING;
            Printer::log(M_ERROR | M_ALERT, "The application caused an exception: %s", e.getMsg());
            std::vector<String> trace = e.getTrace();
            for (std::vector<String>::iterator i = trace.begin(); i != trace.end(); i++)
                Printer::log(M_DEBUG, "%s", i->to_charp());
            r = -1;
        }
        catch (...) {
            m_status = STOPPING;
            Printer::log(M_ERROR | M_ALERT, "The application caused an unknown exception");
            r = -1;
        }
        m_status = STOPPING;

        for (AtExit * ptr = AtExit::s_head; ptr; ptr = ptr->m_next)
            ptr->doExit();

        m_status = STOPPED;
        return r;
    }
  protected:
    int argc;
    char ** argv;
    char ** enve;
  private:
    Status m_status;
    static Main * s_application;
};

#define BALAU_STARTUP \
\
class Application : public Balau::Main { \
  public: \
    virtual int startup() throw (Balau::GeneralException); \
}; \
\
extern "C" { \
    int main(int argc, char ** argv) { \
        setlocale(LC_ALL, ""); \
        Balau::Main mainClass; \
        return mainClass.bootstrap(argc, argv); \
    } \
}

};