0

我有一个 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<> 给出的 CHandle 的复制语义。

谢谢,保罗

4

2 回答 2

3

我不会讨论 boost::shared_ptr 或任何智能 ptr。这里有几个原因,从不同的角度来看,为什么智能指针总是可以而且总是被冗余或被淘汰。

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

现在是第二个,希望不是一个相反的位,其中可怜的旧 OO 继承被忽略,因为包含焦点经常胜出(但是当你为那些不断尖叫的人玩混音时,它与 OO 无关:包含我) . 因此,无论它多么罕见,或者它是 OO、非 OO 还是 O(o) 参数:“继承”在这里获胜。

为什么?因为它是一个可等待句柄的概念,包括 Win32 事件、互斥体、自动重置类型、线程,所有这些除了critical_section(它也有一个深层的支持句柄 - 但在 CLR 和 NT 中都经过特殊处理,加上它有双重性)。因此,它对以下情况具有绝对意义:

typedef CHandleT< HANDLE > WaitHandle;

成为“层次结构”的根,以及底层实现已经是什么的复制语义。

最后,它最终是句柄数据类型的最有效表示,因为它们将模仿您所针对的操作系统并且不需要引用计数或雪崩/涟漪引用计数。

然后是跨平台开发和 boost::thread-ing 并毁了睡前故事:-)

于 2009-11-09T20:59:00.117 回答
2

You don't need to store the handle in CEvent as a shared_ptr. The handle is already shared through CHandleT attribute.

Composition is fine as long as you will not want to use CEvent elements as CHandleT ones (using polymorphism).

于 2009-11-09T21:52:57.027 回答