2013-11-20 5 views
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 
} 

Спасибо!

ответ

1

Если вы используете C++ 11, вы можете использовать интеллектуальные указатели, чтобы поддерживать объект до тех пор, пока последняя ссылка на объект не исчезнет. См. shared_pointer. Если вы не в C++ 11, вы можете использовать boost's version. Если вы не хотите включать эту библиотеку и не находитесь в C++ 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 прекрасно справится с этой задачей. Благодаря! – rbhkamal

Смежные вопросы