Лучший способ защитить функцию обратного вызова от деконструированных классов

0

Что было бы хорошим/лучшим для обеспечения безопасности потоков для объектов обратного вызова? В частности, я пытаюсь предотвратить деконструирование объекта обратного вызова, прежде чем все потоки будут завершены с ним.

Легко закодировать код клиента для обеспечения безопасности потоков, но я ищу способ, который немного более оптимизирован. Например, использование фабричного объекта для генерации объектов обратного вызова. Проблема заключается в отслеживании использования объекта обратного вызова.

Ниже приведен пример кода, который я пытаюсь улучшить.

class CHandlerCallback
{
public:
     CHandlerCallback(){  ...  };
     virtual ~CHandlerCallback(){  ...  };
     virtual OnBegin(UINT nTotal ){  ...  };
     virtual OnStep (UINT nIncrmt){  ...  };
     virtual OnEnd(UINT nErrCode){  ...  };

protected:
      ...
}

static DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
    CHandler* phandler = (CHandler*)lpParameter; 
    phandler ->ThreadProc();
    return 0;
};

class CHandler
{
public:
    CHandler(CHandlerCallback * sink = NULL) {
        m_pSink = sink;
        // Start the server thread. (ThreadProc)
    };
    ~CHandler(){...};

    VOID ThreadProc(LPVOID lpParameter) {
       ... do stuff
       if (m_pSink) m_pSink->OnBegin(..)
       while (not exit) {
           ... do stuff
           if (m_pSink) m_pSink->OnStep(..)
           ... do stuff
       }
       if (m_pSink) m_pSink->OnEnd(..);
    };

private:
    CHandlerCallback * m_pSink;
}

class CSpecial1Callback: public CHandlerCallback
{
public:
     CSpecial1Callback(){  ...  };
     virtual ~CBaseHandler(){  ...  };
     virtual OnStep (UINT nIncrmt){  ...  };
}

class CSpecial2Callback: public CHandlerCallback...

Затем код, который запускает все так, как показано ниже:

int main {
   CSpecial2Callback* pCallback = new CSpecial2Callback();
   CHandler handler(pCallback );
   // Right now the client waits for CHandler to finish before deleting
   // pCallback 
}

Благодарю!

Теги:
multithreading

1 ответ

1
Лучший ответ

Если вы используете С++ 11, вы можете использовать интеллектуальные указатели, чтобы поддерживать объект до тех пор, пока последняя ссылка на объект не исчезнет. См. Shared_pointer. Если вы не в С++ 11, вы можете использовать форсированную версию. Если вы не хотите включать эту библиотеку и не находитесь в С++ 11, вы можете прибегнуть к сохранению внутреннего подсчета потоков с использованием этого объекта и уничтожить объект, когда это число достигнет 0. Обратите внимание, что попытка отслеживать счетчик самостоятельно может быть затруднено, так как вам потребуются атомарные обновления для счетчика.

shared_ptr<CSpecial2Callback> pCallback(new CSpecial2Callback());
CHandler handler(pCallback); // You'll need to change this to take a shared_ptr
... //Rest of code -- when the last reference to 
... //pCallback is used up it will be destroyed.
  • 0
    Я бы также порекомендовал умные указатели подсчета ссылок с защитой потоков. Без C ++ 11 есть библиотеки, которые могут предложить это, например, у Qt есть подходящий QSharedPointer<> но я думаю, что это не вариант здесь.
  • 0
    Я использую C ++ 11 и shared_ptr доступен для меня, я полностью забыл об этом. Хотя я надеялся на решение, которое не зависит от количества ссылок. Но shared_ptr сделает работу хорошо. Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню