~hyuchia/pantheon-mail/fix-1562958

« back to all changes in this revision

Viewing changes to src/engine/state/Machine.vala

  • Committer: Jim Nelson
  • Date: 2011-04-11 23:16:21 UTC
  • Revision ID: git-v1:e3cab0804b129c2d69e9ec8bed28d2369f68a1c0
Email client ho!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2011 Yorba Foundation
 
2
 *
 
3
 * This software is licensed under the GNU Lesser General Public License
 
4
 * (version 2.1 or later).  See the COPYING file in this distribution. 
 
5
 */
 
6
 
 
7
public class Geary.State.Machine {
 
8
    private Geary.State.MachineDescriptor descriptor;
 
9
    private uint state;
 
10
    private Mapping[,] transitions;
 
11
    private Transition? default_transition;
 
12
    private bool locked = false;
 
13
    private bool abort_on_no_transition = true;
 
14
    private bool logging = false;
 
15
    
 
16
    public Machine(MachineDescriptor descriptor, Mapping[] mappings, Transition? default_transition) {
 
17
        this.descriptor = descriptor;
 
18
        this.default_transition = default_transition;
 
19
        
 
20
        // verify that each state and event in the mappings are valid
 
21
        foreach (Mapping mapping in mappings) {
 
22
            assert(mapping.state < descriptor.state_count);
 
23
            assert(mapping.event < descriptor.event_count);
 
24
        }
 
25
        
 
26
        state = descriptor.start_state;
 
27
        
 
28
        // build a transition map with state/event IDs (i.e. offsets) pointing directly into the
 
29
        // map
 
30
        transitions = new Mapping[descriptor.state_count, descriptor.event_count];
 
31
        for (int ctr = 0; ctr < mappings.length; ctr++) {
 
32
            Mapping mapping = mappings[ctr];
 
33
            assert(transitions[mapping.state, mapping.event] == null);
 
34
            transitions[mapping.state, mapping.event] = mapping;
 
35
        }
 
36
    }
 
37
    
 
38
    public uint get_state() {
 
39
        return state;
 
40
    }
 
41
    
 
42
    public bool get_abort_on_no_transition() {
 
43
        return abort_on_no_transition;
 
44
    }
 
45
    
 
46
    public void set_abort_on_no_transition(bool abort) {
 
47
        abort_on_no_transition = abort;
 
48
    }
 
49
    
 
50
    public void set_logging(bool logging) {
 
51
        this.logging = logging;
 
52
    }
 
53
    
 
54
    public bool get_logging() {
 
55
        return logging;
 
56
    }
 
57
    
 
58
    public uint issue(uint event, void *user = null) {
 
59
        assert(event < descriptor.event_count);
 
60
        assert(state < descriptor.state_count);
 
61
        
 
62
        Mapping? mapping = transitions[state, event];
 
63
        
 
64
        Transition transition = (mapping != null) ? mapping.transition : default_transition;
 
65
        if (transition == null) {
 
66
            string msg = "%s: No transition defined at %s for %s".printf(to_string(),
 
67
                descriptor.get_state_string(state), descriptor.get_event_string(event));
 
68
            
 
69
            if (get_abort_on_no_transition())
 
70
                error(msg);
 
71
            else
 
72
                critical(msg);
 
73
            
 
74
            return state;
 
75
        }
 
76
        
 
77
        // guard against reentrancy ... don't want to use a non-reentrant lock because then
 
78
        // the machine will simply hang; assertion is better to ferret out design flaws
 
79
        assert(!locked);
 
80
        locked = true;
 
81
        
 
82
        uint old_state = state;
 
83
        state = transition(state, event, user);
 
84
        assert(state < descriptor.state_count);
 
85
        
 
86
        assert(locked);
 
87
        locked = false;
 
88
        
 
89
        if (get_logging()) {
 
90
            message("%s: State transition from %s to %s due to event %s", to_string(),
 
91
                descriptor.get_state_string(old_state), descriptor.get_state_string(state),
 
92
                descriptor.get_event_string(event));
 
93
        }
 
94
        
 
95
        return state;
 
96
    }
 
97
    
 
98
    public string to_string() {
 
99
        return "Machine %s".printf(descriptor.name);
 
100
    }
 
101
}
 
102