向句柄包装器添加功能

发布于 2024-08-10 19:47:29 字数 2131 浏览 4 评论 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 的复制语义。

谢谢, 保罗·H

I have a C++ RAII class for managing Win32 HANDLEs using boost::shared_ptr<> that looks a bit like this:

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;

I would like to extend it such that instead writing:

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

I could write:

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

Would the best way to do that be to use the CHandle class as a member of a CEvent class?

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

Or, is there a better way? (Note that I still want to maintain the copy semantics of the CHandle given by boost::shared_ptr<>.

Thanks,
PaulH

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

穿透光 2024-08-17 19:47:29

我不会讨论 boost::shared_ptr 或任何智能 ptr。以下是从不同角度看智能指针总是被冗余或被淘汰的几个原因。

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

现在是第二个,希望不是一个矛盾的地方,即可怜的旧式 OO 继承被忽略,因为遏制焦点经常胜出(但当你为那些不断尖叫的人玩混音时,它实际上与 OO 无关:遏制我) 。因此,无论它多么罕见,或者它是 OO、非 OO 还是 O(o) 论证:“继承”在这里获胜。

为什么?因为它是一个可等待句柄概念,包括 Win32 事件、互斥体、自动重置类型、线程,所有这些除了 Critical_section 之外(它内部也有一个后备句柄 - 但在 CLR 和 NT 中都经过特殊处理,而且它还具有双重性)。因此,它绝对有意义:

typedef CHandleT<手柄>等待句柄;

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

最后,它最终成为句柄数据类型的最有效表示,因为它们将模仿您的目标操作系统,并且不需要引用计数或雪崩/波纹引用计数。

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

I won't get into discussion on boost::shared_ptr or any smart ptr. And here is a few reasons why, from different angles between the lines, and why smart pointers can always and always be made redundant or beaten out.

Code does seem to emulate the CLR and NT model in which case there are predefined semantics by the OS for what you're doing. It's called ::DuplicateHandle and it works well and is more suited for cross process scenarios (and would hack less than boost::interprocess or similar). And it is applicable to few other contexts.

Now the second, hopefully not a contraversial bit where the poor-old-OO inheritance is neglected because containment focus wins out regurarly (yet it has nothing to do with OO really when you play mix-ins for those that continously scream: contain me ). So no matter how rare it might be, or whether it is an OO, non-OO or O(o) argument : "inheritance" wins here.

Why? Because it is a waitable handle concept, including the Win32 Event, Mutex, Auto reset kinds, Thread, all of it apart from critical_section (which also has a backing handle deep within - but is specially treated in both CLR and NT, plus it has dual-nature ). Thus it makes absolute sense for:

typedef CHandleT< HANDLE > WaitHandle;

to be the root of the "hierarchy", along with copy semantics of what the underlying implementation already is.

Lastly, it ends up the most efficient representation of your data types that are handles, as they will mimic the OS you are targetting and need no ref count or avalanche/rippling ref count either.

Then came cross-platform development and boost::thread-ing and ruined the bed-time story :-)

几度春秋 2024-08-17 19:47:29

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

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

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文