1 /*****************************************************************************
2 * objres.c: vlc_object_t resources
3 *****************************************************************************
4 * Copyright (C) 2017 RĂ©mi Denis-Courmont
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
30 #include <vlc_common.h>
33 #include "variables.h"
38 void (*release
)(void *);
39 max_align_t payload
[];
42 static struct vlc_res
**vlc_obj_res(vlc_object_t
*obj
)
44 return &vlc_internals(obj
)->resources
;
47 void *vlc_objres_new(size_t size
, void (*release
)(void *))
49 if (unlikely(add_overflow(sizeof (struct vlc_res
), size
, &size
)))
55 struct vlc_res
*res
= malloc(size
);
56 if (unlikely(res
== NULL
))
59 res
->release
= release
;
63 void vlc_objres_push(vlc_object_t
*obj
, void *data
)
65 struct vlc_res
**restrict pp
= vlc_obj_res(obj
);
66 struct vlc_res
*res
= container_of(data
, struct vlc_res
, payload
);
72 static void *vlc_objres_pop(vlc_object_t
*obj
)
74 struct vlc_res
**restrict pp
= vlc_obj_res(obj
);
75 struct vlc_res
*res
= *pp
;
83 void vlc_objres_clear(vlc_object_t
*obj
)
87 while ((data
= vlc_objres_pop(obj
)) != NULL
)
89 struct vlc_res
*res
= container_of(data
, struct vlc_res
, payload
);
91 res
->release(res
->payload
);
96 void vlc_objres_remove(vlc_object_t
*obj
, void *data
,
97 bool (*match
)(void *, void *))
99 struct vlc_res
**restrict pp
= vlc_obj_res(obj
);
101 /* With a doubly-linked list, this function could have constant complexity.
102 * But that would require one more pointer per resource.
104 * Any given list should contain a fairly small number of resources,
105 * and in most cases, the resources are destroyed implicitly by
106 * vlc_objres_clear().
110 struct vlc_res
*res
= *pp
;
112 assert(res
!= NULL
); /* invalid free? */
114 if (match(res
->payload
, data
))
117 res
->release(res
->payload
);
126 static void dummy_release(void *data
)
131 static bool ptrcmp(void *a
, void *b
)
136 void *vlc_obj_malloc(vlc_object_t
*obj
, size_t size
)
138 void *ptr
= vlc_objres_new(size
, dummy_release
);
139 if (likely(ptr
!= NULL
))
140 vlc_objres_push(obj
, ptr
);
144 static void *vlc_obj_alloc_common(vlc_object_t
*obj
, size_t nmemb
, size_t size
,
148 if (mul_overflow(nmemb
, size
, &tabsize
))
154 void *ptr
= vlc_objres_new(tabsize
, dummy_release
);
155 if (likely(ptr
!= NULL
))
158 memset(ptr
, 0, tabsize
);
159 vlc_objres_push(obj
, ptr
);
164 void *vlc_obj_calloc(vlc_object_t
*obj
, size_t nmemb
, size_t size
)
166 return vlc_obj_alloc_common(obj
, nmemb
, size
, true);
169 void vlc_obj_free(vlc_object_t
*obj
, void *ptr
)
171 vlc_objres_remove(obj
, ptr
, ptrcmp
);