]>
Commit | Line | Data |
---|---|---|
72addbc4 | 1 | /* |
2ad0cdc8 | 2 | * Copyright (c) 2010-2012 Red Hat |
72addbc4 AS |
3 | * |
4 | * All rights reserved. | |
5 | * | |
6 | * Author: Angus Salkeld <asalkeld@redhat.com> | |
7 | * | |
8 | * This software licensed under BSD license, the text of which follows: | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions are met: | |
12 | * | |
13 | * - Redistributions of source code must retain the above copyright notice, | |
14 | * this list of conditions and the following disclaimer. | |
15 | * - Redistributions in binary form must reproduce the above copyright notice, | |
16 | * this list of conditions and the following disclaimer in the documentation | |
17 | * and/or other materials provided with the distribution. | |
18 | * - Neither the name of the MontaVista Software, Inc. nor the names of its | |
19 | * contributors may be used to endorse or promote products derived from this | |
20 | * software without specific prior written permission. | |
21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
32 | * THE POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | |
34 | #ifndef FSM_H_DEFINED | |
35 | #define FSM_H_DEFINED | |
36 | ||
37 | #include <sys/time.h> | |
38 | #include <corosync/corotypes.h> | |
39 | #include "util.h" | |
40 | ||
41 | struct cs_fsm; | |
42 | struct cs_fsm_entry; | |
43 | typedef void (*cs_fsm_event_action_fn)(struct cs_fsm* fsm, int32_t event, void * data); | |
44 | typedef const char * (*cs_fsm_state_to_str_fn)(struct cs_fsm* fsm, int32_t state); | |
45 | typedef const char * (*cs_fsm_event_to_str_fn)(struct cs_fsm* fsm, int32_t event); | |
397cc89f JF |
46 | |
47 | typedef void (*cs_fsm_cb)(struct cs_fsm *fsm, int cb_event, int32_t curr_state, | |
48 | int32_t next_state, int32_t fsm_event, void *data); | |
49 | ||
72addbc4 | 50 | #define CS_FSM_NEXT_STATE_SIZE 32 |
397cc89f JF |
51 | |
52 | #define CS_FSM_STATE_NONE -1 | |
53 | ||
54 | #define CS_FSM_CB_EVENT_PROCESS_NF 0 | |
55 | #define CS_FSM_CB_EVENT_STATE_SET 1 | |
56 | #define CS_FSM_CB_EVENT_STATE_SET_NF 2 | |
57 | ||
72addbc4 AS |
58 | struct cs_fsm_entry { |
59 | int32_t curr_state; | |
60 | int32_t event; | |
61 | cs_fsm_event_action_fn handler_fn; | |
62 | int32_t next_states[CS_FSM_NEXT_STATE_SIZE]; | |
63 | }; | |
64 | ||
65 | struct cs_fsm { | |
66 | const char *name; | |
67 | int32_t curr_state; | |
68 | int32_t curr_entry; | |
69 | size_t entries; | |
70 | struct cs_fsm_entry *table; | |
71 | cs_fsm_state_to_str_fn state_to_str; | |
72 | cs_fsm_event_to_str_fn event_to_str; | |
73 | }; | |
74 | ||
75 | /* | |
76 | * the table entry is defined by the state + event (curr_entry). | |
77 | * so cs_fsm_process() sets the entry and cs_fsm_state_set() | |
78 | * sets the new state. | |
79 | */ | |
397cc89f | 80 | static inline void cs_fsm_process (struct cs_fsm *fsm, int32_t new_event, void * data, cs_fsm_cb cb) |
72addbc4 AS |
81 | { |
82 | int32_t i; | |
83 | ||
84 | for (i = 0; i < fsm->entries; i++) { | |
85 | if (fsm->table[i].event == new_event && | |
86 | fsm->table[i].curr_state == fsm->curr_state) { | |
87 | ||
88 | assert (fsm->table[i].handler_fn != NULL); | |
89 | /* set current entry */ | |
90 | fsm->curr_entry = i; | |
91 | fsm->table[i].handler_fn (fsm, new_event, data); | |
92 | return; | |
93 | } | |
94 | } | |
397cc89f JF |
95 | |
96 | if (cb != NULL) { | |
97 | cb(fsm, CS_FSM_CB_EVENT_PROCESS_NF, fsm->curr_state, CS_FSM_STATE_NONE, new_event, data); | |
98 | } | |
72addbc4 AS |
99 | } |
100 | ||
397cc89f | 101 | static inline void cs_fsm_state_set (struct cs_fsm* fsm, int32_t next_state, void* data, cs_fsm_cb cb) |
72addbc4 AS |
102 | { |
103 | int i; | |
104 | struct cs_fsm_entry *entry = &fsm->table[fsm->curr_entry]; | |
105 | ||
106 | if (fsm->curr_state == next_state) { | |
107 | return; | |
108 | } | |
109 | /* | |
110 | * confirm that "next_state" is in the current entry's next list | |
111 | */ | |
112 | for (i = 0; i < CS_FSM_NEXT_STATE_SIZE; i++) { | |
113 | if (entry->next_states[i] < 0) { | |
114 | break; | |
115 | } | |
116 | if (entry->next_states[i] == next_state) { | |
397cc89f JF |
117 | if (cb != NULL) { |
118 | cb(fsm, CS_FSM_CB_EVENT_STATE_SET, fsm->curr_state, next_state, entry->event, data); | |
119 | } | |
72addbc4 AS |
120 | fsm->curr_state = next_state; |
121 | return; | |
122 | } | |
123 | } | |
397cc89f JF |
124 | if (cb != NULL) { |
125 | cb(fsm, CS_FSM_CB_EVENT_STATE_SET_NF, fsm->curr_state, next_state, entry->event, data); | |
126 | } | |
72addbc4 AS |
127 | } |
128 | ||
129 | #endif /* FSM_H_DEFINED */ | |
130 | ||
131 |