向句柄包装器添加功能

时间:2009-11-09 20:41:42

标签: c++ winapi raii

我有一个C ++ RAII类,用于使用boost :: shared_ptr<>来管理Win32 HANDLE。看起来有点像这样:

namespace detail {
struct NoDelete { void operator()( void* ) {}; };
}; // namespace detail

template< typename HANDLE_TYPE, typename HANDLE_DELETER >
class CHandleT
{
public :
    explicit CHandleT( HANDLE_TYPE handle, bool delete_on_release = true )
    {
        if( delete_on_release )
            handle_ = Handle( handle, HANDLE_DELETER() );
        else
            handle_ = Handle( handle, detail::NoDelete() );

    };

    operator HANDLE_TYPE() const { return static_cast< HANDLE_TYPE >( handle_.get() ); };

protected:
    typedef boost::shared_ptr< void > Handle;
    Handle handle_;

}; // class CHandleT

struct DeallocateHandle
{
    void operator()( void* handle ) { ::CloseHandle( handle ); };
};

typedef CHandleT< HANDLE, DeallocateHandle > CHandle;

我想扩展它,而不是写:

CHandle my_handle( ::CreateEvent( NULL, FALSE, FALSE, NULL ) );
::SetEvent( my_handle.get() );

我可以写:

CEvent my_event( NULL, FALSE, FALSE, NULL );
my_event.SetEvent();

最好的方法是使用CHandle类作为CEvent类的成员吗?

class CEvent
{
public:
    explicit CEvent( LPSECURITY_ATTRIBUTES lpEventAttributes = NULL,
                     BOOL bManualReset = TRUE,
                     BOOL bInitialState = FALSE,
                     LPCTSTR lpName = NULL, 
                     bool delete_on_release = true ) :
        handle_( new CHandle( ::CreateEvent( lpEventAttributes, 
                                              bManualReset, 
                                              bInitialState, 
                                              lpName ),
                               delete_on_release ) )
    {
    };

    BOOL SetEvent()
    {
        _ASSERT( NULL != handle_ && NULL != handle_.get() );
        return ::SetEvent( handle_.get() );
    };

private:
    boost::shared_ptr< CHandle > handle_;
}; // class CEvent

或者,有更好的方法吗? (注意,我仍然希望维护由boost :: shared_ptr&lt;&gt;给出的CHandle的复制语义。

谢谢, PaulH

2 个答案:

答案 0 :(得分:3)

我不会讨论boost :: shared_ptr或任何智能ptr。这里有几个原因,从线条之间的不同角度,以及为什么智能指针总是可以永远地被冗余或被打败。

代码似乎模拟了CLR和NT模型,在这种情况下,操作系统会为您正在执行的操作预定义语义。它被称为:: DuplicateHandle,它运行良好,更适合跨进程场景(并且会比boost :: interprocess或类似的更少)。它适用于其他一些情况。

现在是第二个,希望不是一个矛盾的位置,因为遏制焦点会逐渐胜出(但是当你为那些不断尖叫的人玩混音时,它与OO无关)包含我)。所以无论它多么罕见,或者它是否是OO,非OO或O(o)论证:“继承”在这里获胜。

为什么呢?因为它是一个可等待的句柄概念,包括Win32事件,Mutex,自动重置种类,Thread,除了critical_section之外的所有内容(它还有一个内部支持句柄 - 但在CLR和NT中都经过特殊处理,加上它有双重性质)。因此,它绝对有意义:

typedef CHandleT&lt;手柄&gt; WaitHandle的;

是“层次结构”的根,以及底层实现已经存在的复制语义。

最后,它最终会成为处理数据类型的最有效表示,因为它们将模仿您正在定位的操作系统,并且不需要引用计数或雪崩/波纹引用计数。

然后是跨平台开发和提升::线程并破坏了睡前故事: - )

答案 1 :(得分:2)

您不需要将句柄存储在CEvent中作为shared_ptr。句柄已通过CHandleT属性共享。

只要您不想将CEvent元素用作CHandleT元素(使用多态),组合就可以了。