]> code.delx.au - pulseaudio/blob - polyp/polyplib-operation.c
implement proper refcounting in polyplib
[pulseaudio] / polyp / polyplib-operation.c
1 #include <assert.h>
2
3 #include "xmalloc.h"
4 #include "polyplib-internal.h"
5 #include "polyplib-operation.h"
6
7 struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s) {
8 struct pa_operation *o;
9 assert(c);
10
11 o = pa_xmalloc(sizeof(struct pa_operation));
12 o->ref = 1;
13 o->context = pa_context_ref(c);
14 o->stream = s ? pa_stream_ref(s) : NULL;
15
16 o->state = PA_OPERATION_RUNNING;
17 o->userdata = NULL;
18 o->callback = NULL;
19
20 PA_LLIST_PREPEND(struct pa_operation, o->context->operations, o);
21 return pa_operation_ref(o);
22 }
23
24 struct pa_operation *pa_operation_ref(struct pa_operation *o) {
25 assert(o && o->ref >= 1);
26 o->ref++;
27 return o;
28 }
29
30 void pa_operation_unref(struct pa_operation *o) {
31 assert(o && o->ref >= 1);
32
33 if ((--(o->ref)) == 0) {
34 assert(!o->context);
35 assert(!o->stream);
36 free(o);
37 }
38 }
39
40 static void operation_set_state(struct pa_operation *o, enum pa_operation_state st) {
41 assert(o && o->ref >= 1);
42
43 if (st == o->state)
44 return;
45
46 if (!o->context)
47 return;
48
49 o->state = st;
50
51 if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) {
52 PA_LLIST_REMOVE(struct pa_operation, o->context->operations, o);
53 pa_context_unref(o->context);
54 if (o->stream)
55 pa_stream_unref(o->stream);
56 o->context = NULL;
57 o->stream = NULL;
58 o->callback = NULL;
59 o->userdata = NULL;
60
61 pa_operation_unref(o);
62 }
63 }
64
65 void pa_operation_cancel(struct pa_operation *o) {
66 assert(o && o->ref >= 1);
67 operation_set_state(o, PA_OPERATION_CANCELED);
68 }
69
70 void pa_operation_done(struct pa_operation *o) {
71 assert(o && o->ref >= 1);
72 operation_set_state(o, PA_OPERATION_DONE);
73 }
74
75 enum pa_operation_state pa_operation_get_state(struct pa_operation *o) {
76 assert(o && o->ref >= 1);
77 return o->state;
78 }