2016-01-27 3 views
0

У меня есть один случай событийный класс, который имеет очередь и поток на нем. Реализация подобна реализации, существует несколько модулей/объектов, которые подписываются на определенные события и могут отправлять несколько событий.критический раздел для очереди внутри потока

Цель этого класса событий - получить все эти события, нажав их на очередь, и поток внутри этого класса должен заполнить событие и отправить его соответствующим соответствующим подписным модулям/объектам.

Идея создания C++ базы EventAggregator, доступной на C#.

Реализация подобно

void c_eventAggregator::PostEvent(EVENT_UID EventUid) 
{ 
    c_criticalRegion criticalRegion(eASyncObj); 
    Queue.push_back(EventUid); 
    criticalRegion.~c_criticalRegion(); 
} 

void c_eventAggregator::DispatchEventToClients(EVENT_UID EventUid) 
{ 
    EventClientsList eclist = _eventIdSubsList[EventUid]; 

    for (EventClientsList::iterator iter = eclist.begin(); iter != eclist.end(); iter++) { 
     iter->second->receiveEvent(EventUid); 
    } 

} 

int c_eventAggregator::SubscribeEvent(EVENT_CLIENTID clientId, c_eventClient *ecPtr, EVENT_UID EventUid) 
{ 
    try 
    { 
     _eventIdSubsList[EventUid].insert(make_pair(clientId, ecPtr)); 
    } 
    catch (int exception) 
    { 
     return exception; 
    } 
    return ZERO_VALUE; 
} 

void c_eventAggregator::run(void) 
{ 
    EVENT_UID EventUid; 

    while (isAlive()) 
    { 
     while (Queue.size()) 
     { 
      if (!Queue.empty()) 
      { 
       c_criticalRegion criticalRegion(eASyncObj); 
       EventUid = Queue[0]; 
       Queue.pop_front(); 

       DispatchEventToClients(EventUid); 
       criticalRegion.~c_criticalRegion(); 
      } 
     } 
    } 
} 

Я использую критической секции между нажатием и поп-музыки, так что очередь не перезаписываются, если несколько модулей/объект записи одновременно. (Не уверен, что это правильно).

Мой критический обработчик раздел как

class c_criticalRegion{ 
    public: 
    c_criticalRegion(c_syncObject &paSyncObject) : mSyncObject(paSyncObject){ 
     mSyncObject.lock(); 
    } 

    ~c_criticalRegion(){ 
     mSyncObject.unlock(); 
    } 

    private: 
    c_syncObject &mSyncObject; 

}; 

объект синхронизации, как sync.cpp,

c_syncObject::c_syncObject(){ 
    InitializeCriticalSection(&m_oMutexHandle); 
} 

c_syncObject::~c_syncObject(){ 
    DeleteCriticalSection(&m_oMutexHandle); 
} 

synch.h:

class c_syncObject{ 
private: 
protected: 
    //! The win32 CRITICAL_SECTION handle of the operating system. 
    CRITICAL_SECTION m_oMutexHandle; 

public: 
    c_syncObject(); 
    ~c_syncObject(); 
    /*!\brief Lock the resource coming after the lock command 
    * 
    * This function blocks until it will get the lock for the coming critical section. 
    */ 
    void lock(void){ 
     EnterCriticalSection(&m_oMutexHandle); 
     //TODO handle return value 
    }; 
    //!Free the resource coming after the lock command 
    void unlock(void){ 
     LeaveCriticalSection(&m_oMutexHandle); 
     //TODO handle return value 
    }; 
}; 

Issue я сталкиваюсь здесь код не работает, если я не прокомментирую criticalRegion.~c_criticalRegion() внутри PostEven t(). Аналогично, когда есть событие, отправьте на PostEvent, очередь внутри run() по-прежнему показывает размер как ноль.

Это вроде тривиально, когда я получаю такую ​​же ситуацию и в других файлах, которые имеют аналогичный вид реализации.

Также я хотел бы знать, когда выпуск критической секции, после завершения задачи DispatchEventToClients() или раньше.

+0

Кстати, я не знаю вашего варианта использования, но в общем вы должны обернуть 'SubscribeEvent' с критической секции тоже. Если случай кто-то вызывает его во время 'DispatchEventToClients'. –

+0

Вы не должны называть 'criticalRegion. ~ C_criticalRegion()' в 'PostEvent' и' run' вообще.Он будет вызываться автоматически, когда программа выходит из области действия. В вашем случае это называется дважды. –

+0

@MichaelNastenko: Я тебя не понимаю. Вы хотите сказать, не нужно освобождать замок? Если да, то как он понимает длину критической области – kar

ответ

1

Вы не должны явно вызывать деструктор в этом случае. На самом деле, есть так мало случаев, когда вы должны называть это, что вы, вероятно, никогда не столкнетесь с одним из них (у меня только один в моей жизни, и это был грязный хак).

Вот ваша проблема:

void c_eventAggregator::PostEvent(EVENT_UID EventUid) 
{ 
    c_criticalRegion criticalRegion(eASyncObj); 
    Queue.push_back(EventUid); 
    criticalRegion.~c_criticalRegion(); // <<< this is wrong 
} 

К этому коду criticalRegion деструктор будет вызван дважды - один раз и один раз вам компилятором.

Этот тип классов называется защитой, и они помогают избежать явного призыва к «очистке» (LeaveCriticalSection в вашем случае). В вашем случае это неважно, но иногда есть много функций return s, и это беспорядок, чтобы повесить его повсюду. И явный вызов не будет вызываться в случае исключения.

Вы можете проверить простой пример with explicit call и w/o explicit call

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