1 // Written in the D programming language.
2 /++
3  + Authors: KanzakiKino
4  + Copyright: KanzakiKino 2018
5  + License: LGPL-3.0
6 ++/
7 module w4d.app;
8 import w4d.event,
9        w4d.log;
10 import std.algorithm,
11        std.stdio;
12 import core.thread;
13 static import g4d;
14 
15 /// A handler type to catch the exception thrown at inside of main loop.
16 alias ExceptionHandler = EventHandler!( bool, Exception );
17 
18 /// An object of application.
19 /// Manages all tasks executing.
20 class App
21 {
22     protected Task[]   _tasks;
23 
24     /// Duration in milliseconds to sleep in each frames.
25     uint sleepDuration;
26     /// Status code that main function returns.
27     int returnCode;
28 
29     // Arguments of main function.
30     immutable string[] args;
31 
32     /// A handler to catch the exception thrown at inside of main loop.
33     ExceptionHandler onThrown;
34 
35     ///
36     this ( in string[] args )
37     {
38         this.args     = args.idup;
39         sleepDuration = 10;
40     }
41 
42     /// Checks if 1 or more tasks are executing.
43     const @property alive () { return !!_tasks.length; }
44 
45     /// Adds the task.
46     Task addTask ( Task newTask )
47     {
48         _tasks ~= newTask;
49         Log.trace( newTask, "was added as Task." );
50         return newTask;
51     }
52 
53     /// Enters main loop.
54     /// Returns: Status code.
55     int exec ()
56     {
57         while ( alive ) {
58             try {
59                 // Adding tasks is possible inside of remove template.
60                 auto temp = _tasks;
61                 _tasks    = [];
62                 _tasks   ~= temp.remove!( x => x.exec(this) );
63 
64                 g4d.Window.pollEvents();
65                 Thread.sleep( dur!"msecs"( sleepDuration ) );
66 
67             } catch ( Exception e ) {
68                 if ( !onThrown.call( e ) ) {
69                     Log.info( "An exception wasn't caught by anyone." );
70                     throw e;
71                 }
72             }
73         }
74         return returnCode;
75     }
76 
77     /// Terminates all tasks forcibly.
78     /// Escapes from main loop because all tasks will be deleted.
79     void terminate ()
80     {
81         _tasks = [];
82         Log.warn( "App is terminating forcibly." );
83     }
84 }
85 
86 /// An interface of task that App does.
87 interface Task
88 {
89     /// Returns true to notify to finish the task.
90     bool exec ( App );
91 }