Boost logo

Boost :

From: Maxim Yegorushkin (e-maxim_at_[hidden])
Date: 2004-07-08 12:41:29


Maciej Sobczak wrote:

[]

> I wrote a very simple class (see attachments), scoped_handle, which
> encapsulates the resource (whatever it is) and its disposing (whatever
> that means).
> The techniques used are similar to those used in implementation of
> boost::shared_ptr.
> The example file shows how the class can be used to guard resources
> allocated by operator new, fopen, open, etc.

Well, the example has one major drawback - it uses new. The solution with shared_ptr has the same drawback. It looks overkill to use it for such a simple problem.

I believe that scoped_handle must be as lightweight as possible.

There is also a belief that mythical policy based smart pointer will solve the problem, but I needed it yesterday.

I've been using following simple implementation. Not a rocket science but it suited my needs quite well.

#include <boost/noncopyable.hpp>

template<class Handle>
struct scoped_handle_traits
{
        static Handle null() { return Handle(); }
};
        
template<
          class Handle
        , class Pfn
        , Pfn close
        , class Tag
        , class Traits = scoped_handle_traits<Handle>
>
class scoped_handle : private boost::noncopyable
{
public:
        typedef Tag tag_type;
        typedef Handle handle_type;
        typedef Traits traits_type;

public:
        scoped_handle()
                : h_(traits_type::null())
        {}

        explicit scoped_handle(Handle h)
                : h_(h)
        {}

        ~scoped_handle()
        {
                if (traits_type::null() != h_)
                        close(h_);
        }

        Handle& get_ref()
        {
                return h_;
        }

        Handle get() const
        {
                return h_;
        }

        void reset(Handle h)
        {
                scoped_handle(h).swap(*this);
        }

        Handle release()
        {
                Handle t(h_);
                h_ = traits_type::null();
                return t;
        }

        void swap(scoped_handle& other)
        {
                std::swap(h_, other.h_);
        }

private:
        typedef Handle(scoped_handle::*unspecified_bool_type)();

public:
        operator unspecified_bool_type() const
        {
                return traits_type::null() == h_ ? false : &scoped_handle::release;
        }

private:
        Handle h_;
};

Example of usage:

typedef scoped_handle<HANDLE, BOOL(WINAPI*)(HANDLE), &::CloseHandle, class handle_tag> handle;
typedef scoped_handle<HLOCAL, HLOCAL(WINAPI*)(HLOCAL), &::LocalFree, class hlocal_tag> hlocal;

-- 
Maxim Yegorushkin

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk