
Hi All. Some time ago Maxim Yegorushkin suggested use boost/bind to implement lazy ScopeGuard. I evolved this parasitic idea and reused a lot of code from boost/bind by preprocessing to implement make_guard binders. The ScopeGuard can be used as usual: scope_guard g = make_guard( func, args ); What do you think about it? Is it possible to "legalize" such approach? ========= #ifndef SCOPE_GUARD_HPP_INCLUDED #define SCOPE_GUARD_HPP_INCLUDED // scope_guard.hpp #include <boost/bind.hpp> //////////////////////////////////////////////////////////////////////////////////////////////// namespace boost { //////////////////////////////////////////////////////////////////////////////////////////////// namespace _bi { //////////////////////////////////////////////////////////////////////////////////////////////// class scope_guard_base { public: void dismiss() const { do_rollback_ = false; } protected: scope_guard_base(const scope_guard_base& other) : do_rollback_(other.do_rollback_) { other.dismiss(); } scope_guard_base() : do_rollback_(true) {} mutable bool do_rollback_; }; //////////////////////////////////////////////////////////////////////////////////////////////// template<class R, class F, class A> class scope_guard_impl : public scope_guard_base { public: scope_guard_impl(F f, A const& a) : rollback_(f, a) {} ~scope_guard_impl() { if(do_rollback_) rollback_(); } private: bind_t<R,F,A> rollback_; }; //////////////////////////////////////////////////////////////////////////////////////////////// } // namespace _bi //////////////////////////////////////////////////////////////////////////////////////////////// typedef _bi::scope_guard_base const& scope_guard; //////////////////////////////////////////////////////////////////////////////////////////////// // create make_guard() definitions by preprocessing boost::bind() sources #undef BOOST_BIND // it seems like authors forgot about it #define BOOST_BIND make_guard #define bind_t scope_guard_impl //////////////////////////////////////////////////////////////////////////////////////////////// // quotation from boost/bind.hpp // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2001 David Abrahams // function pointers #define BOOST_BIND_CC #define BOOST_BIND_ST #include <boost/bind/bind_cc.hpp> #undef BOOST_BIND_CC #undef BOOST_BIND_ST #ifdef BOOST_BIND_ENABLE_STDCALL #define BOOST_BIND_CC __stdcall #define BOOST_BIND_ST #include <boost/bind/bind_cc.hpp> #undef BOOST_BIND_CC #undef BOOST_BIND_ST #endif #ifdef BOOST_BIND_ENABLE_FASTCALL #define BOOST_BIND_CC __fastcall #define BOOST_BIND_ST #include <boost/bind/bind_cc.hpp> #undef BOOST_BIND_CC #undef BOOST_BIND_ST #endif #ifdef BOOST_BIND_ENABLE_PASCAL #define BOOST_BIND_ST pascal #define BOOST_BIND_CC #include <boost/bind/bind_cc.hpp> #undef BOOST_BIND_ST #undef BOOST_BIND_CC #endif // member function pointers #define BOOST_BIND_MF_NAME(X) X #define BOOST_BIND_MF_CC #include <boost/bind/bind_mf_cc.hpp> #undef BOOST_BIND_MF_NAME #undef BOOST_BIND_MF_CC #ifdef BOOST_MEM_FN_ENABLE_STDCALL #define BOOST_BIND_MF_NAME(X) X##_stdcall #define BOOST_BIND_MF_CC __stdcall #include <boost/bind/bind_mf_cc.hpp> #undef BOOST_BIND_MF_NAME #undef BOOST_BIND_MF_CC #endif #ifdef BOOST_MEM_FN_ENABLE_FASTCALL #define BOOST_BIND_MF_NAME(X) X##_fastcall #define BOOST_BIND_MF_CC __fastcall #include <boost/bind/bind_mf_cc.hpp> #undef BOOST_BIND_MF_NAME #undef BOOST_BIND_MF_CC #endif // end quotation boost/bind.hpp /////////////////////////////////////////////////////////////// #undef BOOST_BIND #undef bind_t //////////////////////////////////////////////////////////////////////////////////////////////// } // namespace boost //////////////////////////////////////////////////////////////////////////////////////////////// #endif // #ifndef SCOPE_GUARD_HPP_INCLUDED ============= Regards, Konstantin Echenko

Konstantin Echenko wrote:
Some time ago Maxim Yegorushkin suggested use boost/bind to implement lazy ScopeGuard. I evolved this parasitic idea and reused a lot of code from boost/bind by preprocessing to implement make_guard binders. The ScopeGuard can be used as usual: scope_guard g = make_guard( func, args ); What do you think about it? Is it possible to "legalize" such approach?
IMO the correct person to ask this question would be Andrei Alexandrescu. However, from my experience, his current scopeguard implementation works very well together with boost.bind and boost.lambda. Stefan

Stefan Slapeta <stefan_nospam_@slapeta.com> wrote: []
However, from my experience, his current scopeguard implementation works very well together with boost.bind and boost.lambda.
The major drawback is that his implementation is not bundled with boost. Making it a boost thing makes it more convenient because I always want a boost::bind functor to do cleanup, so proposed code allows for terser syntax: scope_guard g = make_guard(func, args); instead of: ScopeGuard g = MakeGuard(boost::bind(func, args)); -- Maxim Yegorushkin

"Konstantin Echenko" <clean@pisem.net> wrote in message news:cjovcj$oq$1@sea.gmane.org...
Hi All. Some time ago Maxim Yegorushkin suggested use boost/bind to implement lazy ScopeGuard. I evolved this parasitic idea and reused a lot of code from boost/bind by preprocessing to implement make_guard binders. The ScopeGuard can be used as usual: scope_guard g = make_guard( func, args ); What do you think about it? Is it possible to "legalize" such approach?
In July I posted a minimalist scope_guard: http://groups.yahoo.com/group/boost/files/scope_guard.zip The point was not to include any machinery for binding arguments to functions, leaving that job instead to bind or lambda. It seems to have been mostly ignored on this list, but I use it in my recently accepted iostreams library, so it will be part of boost at least as an implementation detail. I'm hoping to work with Joaquin M Lopez Munoz, who uses a scope_guard in his multi_index library, to put some version of scope_guard in boost/detail. I'll repeat my announcement here: Jonathan Turkanis wrote:
I've uploaded a very simple version of Andrei and Petru's ScopeGuard to the files section: http://groups.yahoo.com/group/boost/files/scope_guard.zip.
It's only smart enough to handle cleanup functions or function objects with the signature 'void f()'; more complex cleanup is easy with Bind or Lambda.
There are two object generators: - make_guard returns a scope guard which propagates exceptions - safe_guard returns a scope guard which catches and ignores exceptions
Similarly, there are two macros - BOOST_SCOPE_GUARD declares an anonymous scope guard which propagates exceptions - BOOST_SAFE_GUARD declares an anonymous scope guard which catches and ignores exceptions
Best Regards, Jonathan
//------------------Example--------------------//
#include <iostream> #include <boost/bind.hpp> #include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> #include <boost/scope_guard.hpp>
void goodbye() { std::cout << "goodbye\n"; }
void crash() { throw 0; }
struct T { void goodbye() { std::cout << "goodbye\n"; } };
// // Expected output: // hello // goodbye // goodbye // goodbye // goodbye // goodbye // int main() { using namespace boost;
T t;
// Scope guard which invokes t.goodbye(). scope_guard g1 = make_guard(boost::bind(&T::goodbye, t));
// Scope guard which invokes goodbye(). scope_guard g2 = make_guard(goodbye);
// Scope guard which executes std::cout << "goodbye\n". scope_guard g3 = make_guard( std::cout << boost::lambda::constant("goodbye\n") );
// Scope guard which invokes crash() in a try-catch block. scope_guard g4 = safe_guard(crash);
// Scope guard which invokes crash(). scope_guard g5 = make_guard(crash); g5.dismiss();
// Scope guard which invokes goodbye(). BOOST_SCOPE_GUARD(goodbye);
// Same. (Shows that generated variable names are working.) BOOST_SCOPE_GUARD(goodbye);
// Scope guard which invokes crash() in a try-catch block. BOOST_SAFE_GUARD(crash);
std::cout << "hello\n"; }

Jonathan Turkanis <technews@kangaroologic.com> wrote: []
In July I posted a minimalist scope_guard:
http://groups.yahoo.com/group/boost/files/scope_guard.zip
The point was not to include any machinery for binding arguments to functions, leaving that job instead to bind or lambda.
It seems to have been mostly ignored on this list, but I use it in my recently accepted iostreams library, so it will be part of boost at least as an implementation detail. I'm hoping to work with Joaquin M Lopez Munoz, who uses a scope_guard in his multi_index library, to put some version of scope_guard in boost/detail.
I remember it was discussed before, but I've only managed to find the head of the thread: http://lists.boost.org/MailArchives/boost/msg52712.php If I am not missing something, the conclusion was to ask boost::bind developers to adopt scope_guard, since the latter one can share almost all the code of the former. And then the thread just died... -- Maxim Yegorushkin

"Maxim Yegorushkin" <e-maxim@yandex.ru> wrote in message news:opsfa76qntti5cme@wkcg6rirwp...
Jonathan Turkanis <technews@kangaroologic.com> wrote:
[]
In July I posted a minimalist scope_guard:
http://groups.yahoo.com/group/boost/files/scope_guard.zip
The point was not to include any machinery for binding arguments to functions, leaving that job instead to bind or lambda.
It seems to have been mostly ignored on this list, but I use it in my recently accepted iostreams library, so it will be part of boost at least as an implementation detail. I'm hoping to work with Joaquin M Lopez Munoz, who uses a scope_guard in his multi_index library, to put some version of scope_guard in boost/detail.
I remember it was discussed before, but I've only managed to find the head of the thread: http://lists.boost.org/MailArchives/boost/msg52712.php
If I am not missing something, the conclusion was to ask boost::bind developers to adopt scope_guard, since the latter one can share almost all the code of the former. And then the thread just died...
I must have missed that discussion. I agree that would be better, but unless/until that happens, I'd like to unfiy the various scope guards and put them in boost/detail. I'd prefer to use a version that doesn't duplicate code from bind. Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:cjpltt$fng$1@sea.gmane.org... []
I must have missed that discussion. I agree that would be better, but unless/until that happens, I'd like to unfiy the various scope guards and put them in boost/detail. I'd prefer to use a version that doesn't duplicate code from bind.
Hm... I'd prefer to duplicate code in library rather than duplicate code by hands every time I use it. Regards, Konstantin Echenko

"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:cjpltt$fng$1@sea.gmane.org...
[]
I must have missed that discussion. I agree that would be better, but unless/until that happens, I'd like to unfiy the various scope guards and
"Konstantin Echenko" <clean@pisem.net> wrote in message news:cjrlrl$6ev$1@sea.gmane.org... put
them in boost/detail. I'd prefer to use a version that doesn't duplicate code from bind.
Hm... I'd prefer to duplicate code in library rather than duplicate code by hands every time I use it.
You don't have to reproduce the code from bind, you only have to *use* it, e.g., make_guard(bind(f, arg)). But I'm sure you know that. An integrated solutation would just save us from typing 'boost::bind' and an extra set of parentheses. Jonathan
participants (5)
-
Jonathan Turkanis
-
Konstantin Echenko
-
Maxim Yegorushkin
-
Pavel Vozenilek
-
Stefan Slapeta