简体   繁体   English

如何保证对象的寿命与成员函数的持续时间匹配?

[英]How can I guarantee an object's lifespan matches the duration of a member function?

I've been making use of callbacks to reduce coupling between some C++ classes. 我一直在使用回调来减少某些C ++类之间的耦合。 To define terms: I'll call the class making the callbacks the caller, and the class receiving the callback the callee. 定义术语:我将调用回调的类称为调用者,将接收回调的类称为被调用者。 Typically (but not necessarily), the callee will own the caller. 通常(但不是必须),被呼叫者将拥有呼叫者。 By design, the caller has no knowledge of the callee. 通过设计,呼叫者不了解被呼叫者。

I'm running into an issue relating to the lifespan of the caller object: It has no guarantee that it will still be alive after making any arbitrary callback. 我遇到了一个与调用者对象的生命周期有关的问题:它不能保证在进行任何任意回调后它仍然会存在。 Take this basic example: 举个基本的例子:

void caller::f()
{
    /* Some work */
    if (...)
    {
        /* [1] Execute callback */
        _callee->callback(this);
    }
    /* [2] Some more work */
}

Say that the callee has dynamically allocated the caller, and has registered for the callback specifically to wait for a certain condition to occur. 假设被呼叫者已经动态分配了呼叫者,并已专门为回调注册以等待特定条件的发生。 When it does, the callee will delete the caller from within the callback at [1]. 完成后,被叫方将从[1]的回调中删除该呼叫者。 If that's the case, control will then return to caller::f, but this will have been deleted, and any code at [2] will more than likely crash. 如果是这样的情况下,控制可能会返回主调::女,但this已经被删除了,并且在任何代码[2]将很可能崩溃。

In the general case, the caller can't assume anything about the callee. 在一般情况下,呼叫者无法承担有关被呼叫者的任何事情。 It doesn't know if the callee owns this , or if it might deallocate this , so I would need some general means of preventing deallocation for the scope of the caller's member function. 它不知道被调用方是否拥有this ,或者它是否可能取消分配this ,因此我将需要一些常规方法来防止在调用方成员函数的作用域内重新分配。

I believe a possible solution revolves around boost::shared_ptrs and enable_shared_from_this , though I've never used it. 我相信可能的解决方案围绕boost::shared_ptrsenable_shared_from_this ,尽管我从未使用过。 Since these callbacks are running very frequently (40+ times per second) on mobile devices with limited processing power, I'm also worried about the overhead of creating and passing out that many shared_ptrs . 由于这些回调在处理能力有限的移动设备上非常频繁地运行(每秒40次以上),因此我也担心创建和shared_ptrs许多shared_ptrs的开销。

Delegation is a pretty common pattern in Objective-C. 委派是Objective-C中非常常见的模式。 I'm far less familiar with common C++ design patterns. 我对常见的C ++设计模式不太熟悉。 Is there any quick-and-easy fix for this issue? 是否有解决此问题的简便方法? If not, how would this design typically be accomplished in C++? 如果没有,通常如何在C ++中完成这种设计?

When the callee delete s caller, caller's destructor is called. 当被调用方delete s调用方时,将调用调用方的析构函数。 It is there that you should make sure f has finished. 在此应确保f已完成。

I am guessing f is a thread, so easiest solution would be: 我猜f是一个线程,所以最简单的解决方案是:

thread: 线:

running = true;
while (!must_exit)
    /* do something */

destuctor: 解构器:

thread->must_exit = true;
while (thread->running)
    sleep(a_little);
/* continue with destruction */

If f is not a thread, the same principle can apply where f makes its object (and through that its destructor) know when it is running and when not. 如果f不是线程,则在f使其对象(并通过其析构函数)知道何时运行以及何时不运行的情况下,可以应用相同的原理。


If you don't want to go with a destructor approach, you can still implement this functionality through a function that the callee calls, telling f to never run again and wait until it stops. 如果您不希望使用析构方法,则仍可以通过被调用方调用的函数来实现此功能,告诉f再也不要运行,直到它停止为止。 Then the callee continues with deletion of caller. 然后,被叫方继续删除呼叫者。

So something like this: 所以像这样:

void caller::f()
{
    if (being_deleted)
        return;
    running = true;
    /* Some work */
    if (...)
    {
        /* [1] Execute callback */
        _callee->callback(this);
    }
    /* [2] Some more work */
    running = false;
}

void caller::make_f_stop()
{
    being_deleted = true;
    while (running)
        sleep(a_little);
}

Go ahead and use the shared pointer, though if possible use std::shared_ptr instead of boost::shared_ptr . 继续并使用共享指针,尽管可能的话,请使用std::shared_ptr而不是boost::shared_ptr It's in the (current) standard library, so no need to add an unnecessary boost dependency. 它在(当前)标准库中,因此无需添加不必要的boost依赖项。 If you're already using boost, then that's fine too. 如果您已经在使用boost,那也很好。

You didn't specify what sort of mobile device you're talking about, but the processors in modern smartphones run at hundreds or thousands of megahertz, and even low-power phones often run Java programs (with garbage collection) just fine. 您没有指定要谈论的移动设备类型,但是现代智能手机中的处理器运行速度高达数百或数千兆赫兹,甚至低功率手机也经常运行Java程序(带有垃圾回收)就可以了。 Shared pointers are basically reference counted. 共享指针基本上是引用计数。 It's not a resource-intensive activity. 这不是资源密集型活动。

If your device is able to actually run the callback more than 40 times per second, I doubt it will have any trouble with shared pointers. 如果您的设备每秒可以实际运行回调超过40次,那么我怀疑共享指针是否会带来麻烦。 Don't prematurely optimize for execution speed. 不要过早地优化执行速度。 DO prematurely optimize for safety and sanity. 请过早优化安全性和卫生性。

The usual way of bypassing code that you can't execute anymore is to throw an exception. 绕过不再执行的代码的通常方法是引发异常。 This should be done by the callee at the point where it would normally return to the caller, after it has deleted the caller. 被呼叫者应在删除呼叫者之后通常返回到呼叫者的位置进行此操作。 The exception would be caught in the caller code at the end of the function. 该函数的末尾将在调用者代码中捕获该异常。

I can't say I like this solution, but I think that stems from the unusual situation of the callee owning the caller. 我不能说我喜欢这种解决方案,但我认为这是由于被呼叫者拥有呼叫者的情况异常。

I don't know how smart pointers would help since there's nobody to own the second copy of the pointer. 我不知道智能指针将如何提供帮助,因为没有人拥有指针的第二个副本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何获得COM对象的成员函数的地址? - How can I get the address of a COM object's member function? 如何为同一个类对象的成员函数保留单独的变量副本? - How can I keep separate variable copy for same class object's member function? 我可以在编译时初始化对象的 C 样式 function 指针,以便它调用对象的成员 function 吗? - Can I initialize an object's C style function pointer at compile time so that it calls the object's member function? 对象的成员函数可以修改另一个对象吗? - Can an object's member function modify another object? 成员 function 指的是对象的成员 function - member function referring to an object's member function 我可以使用EXPECT_CALL来验证模拟对象的构造函数是否多次调用成员函数吗? - Can I use EXPECT_CALL to verify if the mock object's constructor calls a member function certain times? 如何使用该对象的 static 成员 function 初始化 object? - How do I initialize an object using a static member function of that object's class? 如何将对象的成员函数作为std算法的unary_function调用? - How do I call a object's member function as a unary_function for std algorithms? 如何通过将类的对象和成员函数传递给C ++中的另一个函数来调用类? - How do I call a class by passing it's object and member function to another function in c++? 如何使用对象的指针调用对象的成员函数? - How to call a member function of an object using that object's pointer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM