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 *****************************************************************************/
31 #include <vlc_common.h>
34 #include "variables.h"
39 void (*release
)(void *);
40 max_align_t payload
[];
43 static struct vlc_res
**vlc_obj_res(vlc_object_t
*obj
)
45 return &vlc_internals(obj
)->resources
;
48 void *vlc_objres_new(size_t size
, void (*release
)(void *))
50 if (unlikely(add_overflow(sizeof (struct vlc_res
), size
, &size
)))
56 struct vlc_res
*res
= malloc(size
);
57 if (unlikely(res
== NULL
))
60 res
->release
= release
;
64 void vlc_objres_push(vlc_object_t
*obj
, void *data
)
66 struct vlc_res
**restrict pp
= vlc_obj_res(obj
);
67 struct vlc_res
*res
= container_of(data
, struct vlc_res
, payload
);
73 static void *vlc_objres_pop(vlc_object_t
*obj
)
75 struct vlc_res
**restrict pp
= vlc_obj_res(obj
);
76 struct vlc_res
*res
= *pp
;
84 void vlc_objres_clear(vlc_object_t
*obj
)
88 while ((data
= vlc_objres_pop(obj
)) != NULL
)
90 struct vlc_res
*res
= container_of(data
, struct vlc_res
, payload
);
92 res
->release(res
->payload
);
97 void vlc_objres_remove(vlc_object_t
*obj
, void *data
,
98 bool (*match
)(void *, void *))
100 struct vlc_res
**restrict pp
= vlc_obj_res(obj
);
102 /* With a doubly-linked list, this function could have constant complexity.
103 * But that would require one more pointer per resource.
105 * Any given list should contain a fairly small number of resources,
106 * and in most cases, the resources are destroyed implicitly by
107 * vlc_objres_clear().
111 struct vlc_res
*res
= *pp
;
113 assert(res
!= NULL
); /* invalid free? */
115 if (match(res
->payload
, data
))
118 res
->release(res
->payload
);
127 static void dummy_release(void *data
)
132 static bool ptrcmp(void *a
, void *b
)
137 void *vlc_obj_malloc(vlc_object_t
*obj
, size_t size
)
139 void *ptr
= vlc_objres_new(size
, dummy_release
);
140 if (likely(ptr
!= NULL
))
141 vlc_objres_push(obj
, ptr
);
145 void *vlc_obj_calloc(vlc_object_t
*obj
, size_t nmemb
, size_t size
)
148 if (unlikely(mul_overflow(nmemb
, size
, &tabsize
)))
154 void *ptr
= vlc_obj_malloc(obj
, tabsize
);
155 if (likely(ptr
!= NULL
))
156 memset(ptr
, 0, tabsize
);
160 static void *vlc_obj_memdup(vlc_object_t
*obj
, const void *base
, size_t len
)
162 void *ptr
= vlc_obj_malloc(obj
, len
);
163 if (likely(ptr
!= NULL
))
164 memcpy(ptr
, base
, len
);
168 char *vlc_obj_strdup(vlc_object_t
*obj
, const char *str
)
170 return vlc_obj_memdup(obj
, str
, strlen(str
) + 1);
173 void vlc_obj_free(vlc_object_t
*obj
, void *ptr
)
175 vlc_objres_remove(obj
, ptr
, ptrcmp
);