From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29916 invoked by alias); 14 Jan 2019 20:37:47 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 29905 invoked by uid 89); 14 Jan 2019 20:37:47 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-0.9 required=5.0 tests=BAYES_00,KAM_LAZY_DOMAIN_SECURITY,SPF_HELO_PASS autolearn=no version=3.3.2 spammy=bespoke, plate, horrible, sorts X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 14 Jan 2019 20:37:44 +0000 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B1871C009DD1; Mon, 14 Jan 2019 20:37:43 +0000 (UTC) Received: from [127.0.0.1] (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id B89FC100194B; Mon, 14 Jan 2019 20:37:42 +0000 (UTC) Subject: Re: [PATCH 00/12] remove some cleanups using a cleanup function To: Andrew Burgess , gdb-patches@sourceware.org References: <20190109033426.16062-1-tom@tromey.com> Cc: Tom Tromey From: Pedro Alves Message-ID: <961d9501-23e6-9adb-a11b-da41702c4fa0@redhat.com> Date: Mon, 14 Jan 2019 20:37:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-SW-Source: 2019-01/txt/msg00334.txt.bz2 On 01/12/2019 11:50 AM, Andrew Burgess wrote: > I've been thinking about a similar idea for a while too. I wondered > if there was a way we could make use of templates to generate some of > the common boiler plate cleanups. > > This mini-series changes the first 4 of your patches to you this idea > so you can see how it might work. > > First, the ideal, description, a new templated class > `cleanup_function` that allows you to do something like this: > > void > delete_longjmp_breakpoint (int arg) > { > /* Blah, blah, blah... */ > } > > using longjmp_breakpoint_cleanup > = cleanup_function ; It seems unnecessary to pass in the types of the arguments of delete_longjmp_breakpoint. Couldn't those be extracted from delete_longjmp_breakpoint's type? See below. > > This creates a new cleanup class `longjmp_breakpoint_cleanup` than can > then be used like this: > > longjmp_breakpoint_cleanup obj (thread); I think this results in an inferior cleanup_function solution, because this way you can't pass in a bespoke small lambda on the spot. I.e. you're forced to create a cleanup with a named function -- right? If it's the lambda itself you don't like, I think it should be possible to add make cleanup_function's ctor have a std::bind-like interface [1], so that you'd pass cleanup_function's ctor the function and arguments: template cleanup_function (F &&func, Args &&...args); so you'd create the cleanup like: cleanup_function cleanup (delete_longjmp_breakpoint, thread); Since Tromey's cleanup_function is not a template, to implement such a ctor, it would have to rely on std::function (or something like it) for type erasure, which might heap allocate if the resulting callable is large enough. The advantage would be that with that you can create a cleanup_function without passing specifying the called function's type. The disadvantage is the cost of the std::function type erasure / potential heap allocation, of course. But we could avoid the cost/heap if we make cleanup_function a template, as Andrew's version is, but I have to say that I don't really like that version's way of declaring the cleanup_function typedef: +/* Cleanup class that calls delete_longjmp_breakpoint. */ +#ifdef __cpp_template_auto +using longjmp_breakpoint_cleanup + = cleanup_function ; +#else +using longjmp_breakpoint_cleanup += cleanup_function ; +#endif I think it should be possible to code cleanup_function's template such that you could instantiate it like: cleanup_function similarly to gdb::function_view? That doesn't tie cleanup_function to the actual function called, just its type, but I wouldn't see that as a disadvantage, given this way this works with all sorts of callables, including lambdas. Now, ctors don't deduce template parameter types until C++17, so with that template interface and C++11 we wouldn't be able to just write: cleanup_function cleanup (delete_longjmp_breakpoint, 0); But, that is fixable with a helper make_cleanup_function, which would have us write: auto cleanup = make_cleanup_function (delete_longjmp_breakpoint, 0); For the optional cleanup case, we'd need to somehow spell out the type, no way around it, but that's not too horrible with that interface, IMO: cleanup_function cleanup; or: cleanup_function cleanup; (and of course a typedef could put the function's type away from view) I'm not really sure we need a std::bind-like interface though. I'd be super fine with the implementation simplicity of having to pass a lambda, like in scope_exit: auto cleanup = make_scope_exit ([] { delete_longjmp_breakpoint (0); }); ... cleanup.release (); It's simpler to implement, because then all you need for the template parameter type is a generic callable: template class scope_exit ... Note that with Alexandrescu's scope_exit (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4152.pdf), if you don't need to cancel the cleanup, you can write: SCOPE_EXIT { delete_longjmp_breakpoint (0); }; which arguably looks cleaner. Some people prefer avoiding macros that "extend" the C++ language like that, though, I think. [1] https://en.cppreference.com/w/cpp/utility/functional/bind Thanks, Pedro Alves