c++ - critical section for a queue inside a thread -
i have singleton event class has queue , thread on it. implementation like, there several modules/object subscribes event(s) , able post multiple events.
the purpose of event class receive event on push on queue , thread inside class needs pop event , send same respective subscribed modules/objects.
the idea behind creating c++ bases eventaggregator available on c#.
the implementation
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]; (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(); } } } }
i using critical section between push , pop, queue doesn't overwritten when multiple modules/object write @ same time. (not sure whether correct).
my critical section handler like
class c_criticalregion{ public: c_criticalregion(c_syncobject &pasyncobject) : msyncobject(pasyncobject){ msyncobject.lock(); } ~c_criticalregion(){ msyncobject.unlock(); } private: c_syncobject &msyncobject; };
synchronization object sync.cpp,
c_syncobject::c_syncobject(){ initializecriticalsection(&m_omutexhandle); } c_syncobject::~c_syncobject(){ deletecriticalsection(&m_omutexhandle); }
synch.h:
class c_syncobject{ private: protected: //! win32 critical_section handle of operating system. critical_section m_omutexhandle; public: c_syncobject(); ~c_syncobject(); /*!\brief lock resource coming after lock command * * function blocks until lock coming critical section. */ void lock(void){ entercriticalsection(&m_omutexhandle); //todo handle return value }; //!free resource coming after lock command void unlock(void){ leavecriticalsection(&m_omutexhandle); //todo handle return value }; };
issue face here code doesn't work sometime unless comment criticalregion.~c_criticalregion()
inside postevent(). similarly, when there event send postevent, queue inside run()
still shows size zero.
this kind of trivial end getting same situation on other files has similar kind of implementation.
also know, when release critical section, after completing task dispatcheventtoclients()
or before.
you mustn't call destructor explicitly in case. actually, there little cases when should call it, won't ever face 1 of them (i've 1 in life , dirty hack).
here problem:
void c_eventaggregator::postevent(event_uid eventuid) { c_criticalregion criticalregion(easyncobj); queue.push_back(eventuid); criticalregion.~c_criticalregion(); // <<< wrong }
by code criticalregion
destructor called twice - once , once compiler.
this kind of classes called guards , avoid explicit call "clean-up" (leavecriticalsection
in case). in case it's not big deal, there lot of return
s in function , it's mess put everywhere. , explicit call won't called in case of exception.
you can check simple example with explicit call , w/o explicit call
Comments
Post a Comment