From: flameframe_at_[hidden]
Date: 2001-08-13 06:38:30


--- In boost_at_y..., "Alexander Terekhov" <terekhov_at_d...> wrote:
>
> > > > I have written some high level abstractions
> > > > like reader-writer lock using events without getting something
> > like
> > > > CVs in source code.
> > >
> > > could you please show your reader-writer lock using events ?
> > >
> > > regards,
> > > alexander.
> >
> >
> > Just a cut-edit-and-paste from simple redaction of a class:
> >
> > // Comments :
> > // class Mutex - wraps Win32 mutex API
> > // class Event - wraps Win32 event API
> > // class Enter - wraps
WaitForSingleObjectEx/WaitForMultipleObjectsEx
> > API
> > //Usage:
> > //class A : RWLock
> > //{
> > // void read_function() const
> > // {
> > // ReadEnter guard(this);
> > // ....
> > // }
> > // void write_function()
> > // {
> > // WriteEnter guard(this);
> > // ....
> > // }
> > //};
> > struct RWLock
> > {
> > class ReadEnter; class WriteEnter;
> > friend class ReadEnter; friend class WriteEnter;
> >
> > Mutex lock;
> > Event noReaders;
> >
> > int numOfReaders;
> >
> >
> > void oneReaderMore()
> > {
> > numOfReaders++;
> > noReaders = false; //Reset manual reset-event
> > }
> > void oneReaderLess()
> > {
> > if( --numOfReaders == 0 ) // ( no more readers )
> > {
> > noReaders = true; //Set manual reset-event
> > }
> > }
> > RWLock()
> > {
> > numOfReaders = 0 ;
> > noReaders = true ;
> > }
> >
> > class ReadEnter
> > {
> > RWLock* s;
> > DWORD timeout;
> > public:
> > explicit ReadEnter( RWLock*s_
> > , DWORD timeout_=INFINITE)
> > : s(s_),timeout(timeout_)
> > {
> > Enter e(s->lock,timeout);
> > s->oneReaderMore();
> > }
> > ~ReadEnter()
> > {
> > Enter e(s->lock,timeout);
> > s->oneReaderLess();
> > }
> > };
> > class WriteEnter : public Enter
> > {
> > public:
> > explicit WriteEnter( RWLock*s_
> > , DWORD timeout=INFINITE)
> > : Enter(s->lock, s->noReaders
> > , waitAll, timeout)
> > {
> > }
> > };
> > };
>
> thanks. note however, while using WaitForMultiple( mutex, event... )
> you have precluded various race conditions but you are paying rather
> high price for it:
>
> a) you have to synchronize quite expensive set/reset event calls
> (you do it with mutex locked making internal event synchronization
> just a useless/boring overhead for you);

Probably you are right. I am not sure how much work is performed in a
background of SetEvent call. With respect to example you mentioned:
 
- some lock in my code requires
   lock/unlock mutex + set event call
- in Programming with POSIX Threads
   lock/unlock mutex + CV management

I am by no means a threading expert but from the above I can not make
deduction that event's price is higher.

>
> b) with WaitForMultiple( mutex, event... ) you have introduced
> another monitor (it watches the states of multiple synch.
> objects) which means that you've got even more internal locking
> and redundant internal signaling/wakeups/checks/block-again and/or
> internal transfer of synch. objects (mutex) ownership across thread
> context switches..
>

Again, it depends on hidden implemetation details same way as in my
previous comment. If you are a Win32 guru I can believe to you that
you are right (staying with my own opinion although :). It would be
nice to see some time comparisions.

> Q) taking into account the issues above do you still think that
> your solution is better than (or just "equal to") some CV(s)
> based solution; e.g:
>
> http://www.aw.com/cseng/titles/0-201-63392-2/code/rwlock.c
>
> ?
>
> regards,
> alexander.

Who knows? I am far from saying that my solution (to do the justice-
actually there were a lot of people before me writing the same) is
*better* than anyone's else.

Anyway, I have mentioned event-based solutions just to object that it
always result either to race conditions or to CV-equivalent.

As long as performance is a matter of question I (personally) prefer
events in this special case because it (comparing to 'Programming
with POSIX Threads' example) needs less code and is easier to
understand.

Regards,
Vitalij.