1 /*
2  * Cogl
3  *
4  * A Low Level GPU Graphics and Utilities API
5  *
6  * Copyright (C) 2012,2013 Intel Corporation.
7  *
8  * Permission is hereby granted, free of charge, to any person
9  * obtaining a copy of this software and associated documentation
10  * files (the "Software"), to deal in the Software without
11  * restriction, including without limitation the rights to use, copy,
12  * modify, merge, publish, distribute, sublicense, and/or sell copies
13  * of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be
17  * included in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
23  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26  * SOFTWARE.
27  *
28  */
29 
30 #ifndef _COGL_CLOSURE_LIST_PRIVATE_H_
31 #define _COGL_CLOSURE_LIST_PRIVATE_H_
32 
33 #include "cogl-object.h"
34 #include "cogl-list.h"
35 
36 /*
37  * This implements a list of callbacks that can be used a bit like
38  * signals in GObject, but that don't have any marshalling overhead.
39  *
40  * The idea is that any Cogl code that wants to provide a callback
41  * point will provide api to add a callback for that particular point.
42  * The function can take a function pointer with the correct
43  * signature.  Internally the Cogl code can use _cogl_closure_list_add,
44  * _cogl_closure_disconnect and _cogl_closure_list_disconnect_all
45  *
46  * In the future we could consider exposing the CoglClosure type which
47  * would allow applications to use _cogl_closure_disconnect() directly
48  * so we don't need to expose new disconnect apis for each callback
49  * point.
50  */
51 
52 typedef struct _CoglClosure
53 {
54   CoglList link;
55 
56   void *function;
57   void *user_data;
58   CoglUserDataDestroyCallback destroy_cb;
59 } CoglClosure;
60 
61 /*
62  * _cogl_closure_disconnect:
63  * @closure: A closure connected to a Cogl closure list
64  *
65  * Removes the given closure from the callback list it is connected to
66  * and destroys it. If the closure was created with a destroy function
67  * then it will be invoked. */
68 void
69 _cogl_closure_disconnect (CoglClosure *closure);
70 
71 void
72 _cogl_closure_list_disconnect_all (CoglList *list);
73 
74 CoglClosure *
75 _cogl_closure_list_add (CoglList *list,
76                         void *function,
77                         void *user_data,
78                         CoglUserDataDestroyCallback destroy_cb);
79 
80 /*
81  * _cogl_closure_list_invoke:
82  * @list: A pointer to a CoglList containing CoglClosures
83  * @cb_type: The name of a typedef for the closure callback function signature
84  * @...: The the arguments to pass to the callback
85  *
86  * A convenience macro to invoke a closure list with a variable number
87  * of arguments that will be passed to the closure callback functions.
88  *
89  * Note that the arguments will be evaluated multiple times so it is
90  * not safe to pass expressions that have side-effects.
91  *
92  * Note also that this function ignores the return value from the
93  * callbacks. If you want to handle the return value you should
94  * manually iterate the list and invoke the callbacks yourself.
95  */
96 #define _cogl_closure_list_invoke(list, cb_type, ...)   \
97   G_STMT_START {                                        \
98     CoglClosure *_c, *_tmp;                             \
99                                                         \
100     _cogl_list_for_each_safe (_c, _tmp, (list), link)   \
101       {                                                 \
102         cb_type _cb = _c->function;                     \
103         _cb (__VA_ARGS__, _c->user_data);               \
104       }                                                 \
105   } G_STMT_END
106 
107 #define _cogl_closure_list_invoke_no_args(list)         \
108   G_STMT_START {                                        \
109     CoglClosure *_c, *_tmp;                             \
110                                                         \
111     _cogl_list_for_each_safe (_c, _tmp, (list), link)   \
112       {                                                 \
113         void (*_cb)(void *) = _c->function;             \
114         _cb (_c->user_data);                            \
115       }                                                 \
116   } G_STMT_END
117 
118 #endif /* _COGL_CLOSURE_LIST_PRIVATE_H_ */
119