开发者

pthread windows event equivalent question

I have the following code which replicates the windows manual and auto reset events.

class event
{
public:
    event( bool signalled = false, bool ar = true ) :
        _auto( ar ),
        _signalled( signalled )
    {
        pthread_mutex_init( &_mutex, NULL );
        pthread_cond_init( &_cond, NULL );
    }

    ~event()
    {
        pthread_cond_destroy( &_cond );
        pthread_mutex_destroy( &开发者_StackOverflow_mutex );
    }

    void set()
    {
        pthread_mutex_lock( &_mutex );

        // only set and signal if we are unset
        if ( _signalled == false )
        {
            _signalled = true;

            pthread_cond_signal( &_cond );
        }

        pthread_mutex_unlock( &_mutex );
    }

    void wait()
    {
        pthread_mutex_lock( &_mutex );

        while ( _signalled == false )
        {
            pthread_cond_wait( &_cond, &_mutex );
        }

        // if we're an autoreset event, auto reset
        if ( _auto )
        {
            _signalled = false;
        }

        pthread_mutex_unlock( &_mutex );
    }

    void reset()
    {
        pthread_mutex_lock( &_mutex );

        _signalled = false;

        pthread_mutex_unlock( &_mutex );
    }

private:
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    bool _signalled;
    bool _auto;
};

My question surrounds the "optimisation" I've put in place in the set() method where I only call pthread_cond_signal() if the event was unsignalled. Is this a valid optimisation or have I introduced some subtle flaw by doing so.


There's definitely a difference in behavior due to that "optimization" if multiple threads are waiting for the same event. Consider this sequence of events (manual reset mode):

thread 1 - wait
thread 2 - wait
thread 3 - wait
thread 4 - set
thread 4 - set
thread 4 - set
thread 4 - reset

With your code, pthread_cond_signal will only be called once (unblocking one of threads 1-3); without the optimization it would be called 3 times (unblocking all 3 of them).

I don't know if that's a "flaw" or not, because I don't know the precise semantics of the Windows API you're emulating.


For non-auto-reset events, you only wake one thread on a call to set, but you stop additional threads from blocking. That doesn't seem sane to me and creates a race condition between waiters and wakers.


It looks to me that a waiting thread would have ownership of the mutex that protects the desired event behaviour. Since that mutex would be owned when a thread is waiting, nothing else can send a signal and release it.

Since this code is intended to mimic an event, it fails because Windows event objects work satisfactorily. The issue I describe makes the original optimisation question seem irrelevant.

I'm here because I'm thinking about writing portable, multi-threaded code between Windows and Linux. This question helped me to think about what I wanted to do, but I did notice a problem with the code example that no-one seems to have mentioned.


I'd qualify _signalled with volatile, to prevent any clever compiler tricks regarding that variable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜