don't hit an assetr if there are operations outstanding when the pa_context is destroyed
[profile/ivi/pulseaudio.git] / src / pulse / operation.c
1 /* $Id$ */
2
3 /***
4   This file is part of PulseAudio.
5  
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2 of the License,
9   or (at your option) any later version.
10  
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <assert.h>
27
28 #include <pulse/xmalloc.h>
29
30 #include "internal.h"
31 #include "operation.h"
32
33 pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata) {
34     pa_operation *o;
35     assert(c);
36
37     o = pa_xnew(pa_operation, 1);
38     o->ref = 1;
39     o->context = c;
40     o->stream = s;
41
42     o->state = PA_OPERATION_RUNNING;
43     o->callback = cb;
44     o->userdata = userdata;
45
46     /* Refcounting is strictly one-way: from the "bigger" to the "smaller" object. */
47     PA_LLIST_PREPEND(pa_operation, c->operations, o);
48     pa_operation_ref(o);
49     
50     return o;
51 }
52
53 pa_operation *pa_operation_ref(pa_operation *o) {
54     assert(o);
55     assert(o->ref >= 1);
56     
57     o->ref++;
58     return o;
59 }
60
61 void pa_operation_unref(pa_operation *o) {
62     assert(o);
63     assert(o->ref >= 1);
64
65     if ((--(o->ref)) == 0) {
66         assert(!o->context);
67         assert(!o->stream);
68         pa_xfree(o);
69     }
70 }
71
72 static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
73     assert(o);
74     assert(o->ref >= 1);
75
76     if (st == o->state)
77         return;
78
79     pa_operation_ref(o);
80
81     o->state = st;
82
83     if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) {
84         
85         if (o->context) {
86             assert(o->ref >= 2);
87             
88             PA_LLIST_REMOVE(pa_operation, o->context->operations, o);
89             pa_operation_unref(o);
90         }
91         
92         o->context = NULL;
93         o->stream = NULL;
94         o->callback = NULL;
95         o->userdata = NULL;
96     }
97
98     pa_operation_unref(o);
99 }
100
101 void pa_operation_cancel(pa_operation *o) {
102     assert(o);
103     assert(o->ref >= 1);
104     
105     operation_set_state(o, PA_OPERATION_CANCELED);
106 }
107
108 void pa_operation_done(pa_operation *o) {
109     assert(o);
110     assert(o->ref >= 1);
111     
112     operation_set_state(o, PA_OPERATION_DONE);
113 }
114
115 pa_operation_state_t pa_operation_get_state(pa_operation *o) {
116     assert(o);
117     assert(o->ref >= 1);
118
119     return o->state;
120 }