Hi, It took me longer to sit down and write this mail but here it goes. There was a lot of ideas about the macro design and it's easy to get lost in all the designs. So we agreed on this form: # define VIR_AUTOPTR_FUNC_NAME(type) virAutoPtr##type # define VIR_AUTOCLEAR_FUNC_NAME(type) virAutoClear##type # define VIR_DEFINE_AUTOPTR_FUNC(type, func) \ static inline void VIR_AUTOPTR_FUNC_NAME(type)(type *_ptr) \ { \ (func)(*_ptr); \ } # define VIR_DEFINE_AUTOCLEAR_FUNC(type, func) \ static inline void VIR_AUTOCLEAR_FUNC_NAME(type)(type *_ptr) \ { \ (func)(_ptr); \ } # define VIR_AUTOFREE(type) __attribute__((cleanup(virFree))) type # define VIR_AUTOPTR(type) \ __attribute__((cleanup(VIR_AUTOPTR_FUNC_NAME(type)))) type # define VIR_AUTOCLEAR(type) \ __attribute__((cleanup(VIR_AUTOCLEAR_FUNC_NAME(type)))) type but it turned out the it's not sufficient for several reasons: - there is no simple way ho to free list of strings (char **) - this will not work for external types with their own free function In order to solve these two issues there were some ideas. 1. How to handle list of strings We have virStringListFree() function in order to free list of strings, the question is how to use it with these macros: - Create a new typedef for list of strings and use VIR_AUTOPTR: typedef char **virStringList; VIR_DEFINE_AUTOPTR_FUNC(virStringList, virStringListFree); VIR_AUTOPTR(virStringList) list = NULL; The benefit of this solution is that it works with current design and we only need to create single typedef. - Overload VIR_AUTOFREE macro by making it variadic # define _VIR_AUTOFREE_0(type) __attribute__((cleanup(virFree))) type # define _VIR_AUTOFREE_1(type, func) __attribute__((cleanup(func))) type # define _VIR_AUTOFREE_OVERLOADER(_1, _2, NAME, ...) NAME # define VIR_AUTOFREE(...) _VIR_AUTOFREE_OVERLOADER(__VA_ARGS__, _VIR_AUTOFREE_1, _VIR_AUTOFREE_0)(__VA_ARGS__) This would allow us to use any existing function directly with attribute cleanup. However, the function must take as argument pointer to the specified type so we would have to create a wrapper functions which would be used in the VIR_AUTOFREE macro, for example: void virStringListPtrFree(char ***stringsp) { virStringListFree(*stringsp); } VIR_AUTOFREE(char **, virStringListPtrFree) list = NULL; 2. External types with free function Libvirt uses a lot of external libraries where we use the types and relevant free functions. The issue with original design is that it was counting on the fact that we would have vir*Ptr typedefs, but that's not the case for external types. - We can modify the design to be closer to GLib design which would work even with external types and would be safe in case external free functions will not behave correctly. These are to modification to the original design: # define VIR_AUTOPTR_TYPE_NAME(type) ##typeAutoPtr # define VIR_DEFINE_AUTOPTR_FUNC(type, func) \ typedef type *VIR_AUTOPTR_TYPE_NAME(type); static inline void VIR_AUTOPTR_FUNC_NAME(type)(type **_ptr) \ { \ if (*_ptr) { \ (func)(*_ptr); \ *_ptr = NULL; \ } \ } # define VIR_AUTOPTR(type) \ __attribute__((cleanup(VIR_AUTOPTR_FUNC_NAME(type)))) VIR_AUTOPTR_TYPE_NAME(type) The usage would not require our internal vir*Ptr types and would be easy to use with external types as well: VIR_DEFINE_AUTOPTR_FUNC(virBitmap, virBitmapFree); VIR_AUTOPTR(virBitmap) map = NULL; VIR_DEFINE_AUTOPTR_FUNC(LIBSSH2_CHANNEL, libssh2_channel_free); VIR_AUTOPTR(LIBSSH2_CHANNEL) channel = NULL; There was one suggestion to make another set of macros for the external types or just ignore them because there are only few places which uses external free functions. Pavel
Attachment:
signature.asc
Description: PGP signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list