1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains interface to the command queue
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29 void ladish_cqueue_init(struct ladish_cqueue
* queue_ptr
)
31 queue_ptr
->cancel
= false;
32 INIT_LIST_HEAD(&queue_ptr
->queue
);
35 void ladish_cqueue_run(struct ladish_cqueue
* queue_ptr
)
37 struct list_head
* node_ptr
;
38 struct ladish_command
* cmd_ptr
;
41 if (list_empty(&queue_ptr
->queue
))
46 node_ptr
= queue_ptr
->queue
.next
;
47 cmd_ptr
= list_entry(node_ptr
, struct ladish_command
, siblings
);
49 ASSERT(cmd_ptr
->run
!= NULL
);
50 ASSERT(cmd_ptr
->state
== LADISH_COMMAND_STATE_PENDING
|| cmd_ptr
->state
== LADISH_COMMAND_STATE_WAITING
);
52 if (cmd_ptr
->state
== LADISH_COMMAND_STATE_PENDING
)
53 { /* if this is a new command, put a separator so its impact is clearly visible in the log */
57 if (!cmd_ptr
->run(cmd_ptr
->context
))
59 ladish_cqueue_clear(queue_ptr
);
63 switch (cmd_ptr
->state
)
65 case LADISH_COMMAND_STATE_DONE
:
67 case LADISH_COMMAND_STATE_WAITING
:
70 log_error("unexpected cmd state %u after run()", cmd_ptr
->state
);
72 ladish_cqueue_clear(queue_ptr
);
78 if (cmd_ptr
->destructor
!= NULL
)
80 cmd_ptr
->destructor(cmd_ptr
->context
);
85 if (queue_ptr
->cancel
&& list_empty(&queue_ptr
->queue
));
87 queue_ptr
->cancel
= false;
93 void ladish_cqueue_cancel(struct ladish_cqueue
* queue_ptr
)
95 struct list_head
* node_ptr
;
96 struct ladish_command
* cmd_ptr
;
98 if (list_empty(&queue_ptr
->queue
))
99 { /* nothing to cancel */
103 node_ptr
= queue_ptr
->queue
.next
; /* current command */
104 cmd_ptr
= list_entry(node_ptr
, struct ladish_command
, siblings
);
105 if (cmd_ptr
->state
!= LADISH_COMMAND_STATE_WAITING
)
107 ladish_cqueue_clear(queue_ptr
);
111 /* clear all commands except currently waiting one */
112 while (queue_ptr
->queue
.next
!= queue_ptr
->queue
.prev
)
114 node_ptr
= queue_ptr
->queue
.prev
;
117 cmd_ptr
= list_entry(node_ptr
, struct ladish_command
, siblings
);
119 if (cmd_ptr
->destructor
!= NULL
)
121 cmd_ptr
->destructor(cmd_ptr
->context
);
127 queue_ptr
->cancel
= true;
128 cmd_ptr
->cancel
= true;
131 bool ladish_cqueue_add_command(struct ladish_cqueue
* queue_ptr
, struct ladish_command
* cmd_ptr
)
133 ASSERT(cmd_ptr
->run
!= NULL
);
135 if (queue_ptr
->cancel
)
140 ASSERT(cmd_ptr
->state
== LADISH_COMMAND_STATE_PREPARE
);
141 cmd_ptr
->state
= LADISH_COMMAND_STATE_PENDING
;
143 list_add_tail(&cmd_ptr
->siblings
, &queue_ptr
->queue
);
147 void ladish_cqueue_clear(struct ladish_cqueue
* queue_ptr
)
149 struct list_head
* node_ptr
;
150 struct ladish_command
* cmd_ptr
;
152 while (!list_empty(&queue_ptr
->queue
))
154 node_ptr
= queue_ptr
->queue
.next
;
157 cmd_ptr
= list_entry(node_ptr
, struct ladish_command
, siblings
);
159 if (cmd_ptr
->destructor
!= NULL
)
161 cmd_ptr
->destructor(cmd_ptr
->context
);
167 queue_ptr
->cancel
= false;
170 void ladish_cqueue_drop_command(struct ladish_cqueue
* queue_ptr
)
172 struct list_head
* node_ptr
;
173 struct ladish_command
* cmd_ptr
;
175 ASSERT(!list_empty(&queue_ptr
->queue
)); /* there is nothing to drop */
177 /* remove the last command from the queue */
178 node_ptr
= queue_ptr
->queue
.prev
;
180 cmd_ptr
= list_entry(node_ptr
, struct ladish_command
, siblings
);
182 ASSERT(cmd_ptr
->run
!= NULL
);
184 /* waiting commands are not supposed to be dropped */
185 /* commands that are not yet prepared and those that are already processed are not supposed to be in the queue */
186 ASSERT(cmd_ptr
->state
== LADISH_COMMAND_STATE_PENDING
);
188 if (cmd_ptr
->destructor
!= NULL
)
190 cmd_ptr
->destructor(cmd_ptr
->context
);
196 void * ladish_command_new(size_t size
)
198 struct ladish_command
* cmd_ptr
;
200 ASSERT(size
>= sizeof(struct ladish_command
));
202 cmd_ptr
= malloc(size
);
205 log_error("malloc failed to allocate command with size %zu", size
);
209 cmd_ptr
->state
= LADISH_COMMAND_STATE_PREPARE
;
210 cmd_ptr
->cancel
= false;
212 cmd_ptr
->context
= cmd_ptr
;
214 cmd_ptr
->destructor
= NULL
;