示例#1
0
文件: misc.cpp 项目: beanhome/dev
void MiscThreadTestCase::TestThreadSuspend()
{
    MyDetachedThread *thread = new MyDetachedThread(15, 'X');

    CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread->Run() );

    // this is for this demo only, in a real life program we'd use another
    // condition variable which would be signaled from wxThread::Entry() to
    // tell us that the thread really started running - but here just wait a
    // bit and hope that it will be enough (the problem is, of course, that
    // the thread might still not run when we call Pause() which will result
    // in an error)
    wxMilliSleep(300);

    for ( size_t n = 0; n < 3; n++ )
    {
        thread->Pause();

        if ( n > 0 )
        {
            // don't sleep but resume immediately the first time
            wxMilliSleep(300);
        }

        CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, thread->Resume() );
    }

    // wait until the thread terminates
    CPPUNIT_ASSERT_EQUAL( wxSEMA_NO_ERROR, gs_cond.Wait() );
}
示例#2
0
void wxThreadInternal::Resume()
{
    wxCHECK_RET( m_state == STATE_PAUSED,
                 wxT("can't resume thread which is not suspended.") );

    // the thread might be not actually paused yet - if there were no call to
    // TestDestroy() since the last call to Pause() for example
    if ( IsReallyPaused() )
    {
       wxLogTrace(TRACE_THREADS,
                  _T("Waking up thread %ld"), THR_ID(this));

        // wake up Pause()
        m_semSuspend.Post();

        // reset the flag
        SetReallyPaused(false);
    }
    else
    {
        wxLogTrace(TRACE_THREADS,
                   _T("Thread %ld is not yet really paused"), THR_ID(this));
    }

    SetState(STATE_RUNNING);
}
示例#3
0
wxCondError wxConditionInternal::Wait()
{
    // increment the number of waiters
    {
        wxCriticalSectionLocker lock(m_csWaiters);
        m_numWaiters++;
    }

    m_mutex.Unlock();

    // after unlocking the mutex other threads may Signal() us, but it is ok
    // now as we had already incremented m_numWaiters so Signal() will post the
    // semaphore and decrement m_numWaiters back even if it is called before we
    // start to Wait()
    const wxSemaError err = m_semaphore.Wait();

    m_mutex.Lock();

    if ( err == wxSEMA_NO_ERROR )
    {
        // m_numWaiters was decremented by Signal()
        return wxCOND_NO_ERROR;
    }

    // but in case of an error we need to do it manually
    {
        wxCriticalSectionLocker lock(m_csWaiters);
        m_numWaiters--;
    }

    return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
}
示例#4
0
文件: misc.cpp 项目: beanhome/dev
void MyDetachedThread::OnExit()
{
    //wxLogTrace(wxT("thread"), wxT("Thread %ld is in OnExit"), GetId());

    wxCriticalSectionLocker lock(gs_critsect);
    if ( !--gs_counter && !m_cancelled )
        gs_cond.Post();
}
示例#5
0
wxCondError wxConditionInternal::WaitTimeout(unsigned long milliseconds)
{
    {
        wxCriticalSectionLocker lock(m_csWaiters);
        m_numWaiters++;
    }

    m_mutex.Unlock();

    wxSemaError err = m_semaphore.WaitTimeout(milliseconds);

    m_mutex.Lock();

    if ( err == wxSEMA_NO_ERROR )
        return wxCOND_NO_ERROR;

    if ( err == wxSEMA_TIMEOUT )
    {
        // a potential race condition exists here: it happens when a waiting
        // thread times out but doesn't have time to decrement m_numWaiters yet
        // before Signal() is called in another thread
        //
        // to handle this particular case, check the semaphore again after
        // acquiring m_csWaiters lock -- this will catch the signals missed
        // during this window
        wxCriticalSectionLocker lock(m_csWaiters);

        err = m_semaphore.WaitTimeout(0);
        if ( err == wxSEMA_NO_ERROR )
            return wxCOND_NO_ERROR;

        // we need to decrement m_numWaiters ourselves as it wasn't done by
        // Signal()
        m_numWaiters--;

        return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
    }

    // undo m_numWaiters++ above in case of an error
    {
        wxCriticalSectionLocker lock(m_csWaiters);
        m_numWaiters--;
    }

    return wxCOND_MISC_ERROR;
}
示例#6
0
void wxThreadInternal::Pause()
{
    // the state is set from the thread which pauses us first, this function
    // is called later so the state should have been already set
    wxCHECK_RET( m_state == STATE_PAUSED,
                 wxT("thread must first be paused with wxThread::Pause().") );

    // wait until the semaphore is Post()ed from Resume()
    m_semSuspend.Wait();
}
示例#7
0
wxCondError wxConditionInternal::WaitTimeout( unsigned long milliseconds )
{
    IncrementAtomic( &m_numWaiters );

    m_mutex.Unlock();

    // a race condition can occur at this point in the code
    //
    // please see the comments in Wait(), for details

    wxSemaError err = m_semaphore.WaitTimeout(milliseconds);

    if ( err == wxSEMA_TIMEOUT )
    {
        // another potential race condition exists here it is caused when a
        // 'waiting' thread timesout, and returns from WaitForSingleObject, but
        // has not yet decremented 'nwaiters'.
        //
        // at this point if another thread calls signal() then the semaphore
        // will be incremented, but the waiting thread will miss it.
        //
        // to handle this particular case, the waiting thread calls
        // WaitForSingleObject again with a timeout of 0, after locking
        // 'nwaiters_mutex'. this call does not block because of the zero
        // timeout, but will allow the waiting thread to catch the missed
        // signals.
        wxCriticalSectionLocker lock(m_csWaiters);

        err = m_semaphore.WaitTimeout(0);

        if ( err != wxSEMA_NO_ERROR )
        {
            m_numWaiters--;
        }
    }

    m_mutex.Lock();

    return err == wxSEMA_NO_ERROR ? wxCOND_NO_ERROR : wxCOND_MISC_ERROR;
}
示例#8
0
文件: misc.cpp 项目: beanhome/dev
void MiscThreadTestCase::TestThreadConditions()
{
    wxMutex mutex;
    wxCondition condition(mutex);

    // otherwise its difficult to understand which log messages pertain to
    // which condition
    //wxLogTrace(wxT("thread"), wxT("Local condition var is %08x, gs_cond = %08x"),
    //           condition.GetId(), gs_cond.GetId());

    // create and launch threads
    MyWaitingThread *threads[10];

    size_t n;
    for ( n = 0; n < WXSIZEOF(threads); n++ )
    {
        threads[n] = new MyWaitingThread( &mutex, &condition );
    }

    for ( n = 0; n < WXSIZEOF(threads); n++ )
    {
        CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, threads[n]->Run() );
    }

    // wait until all threads run
    // NOTE: main thread is waiting for the other threads to start
    size_t nRunning = 0;
    while ( nRunning < WXSIZEOF(threads) )
    {
        CPPUNIT_ASSERT_EQUAL( wxSEMA_NO_ERROR, gs_cond.Wait() );

        nRunning++;

        // note that main thread is already running
    }

    wxMilliSleep(500);

#if 1
    // now wake one of them up
    CPPUNIT_ASSERT_EQUAL( wxCOND_NO_ERROR, condition.Signal() );
#endif

    wxMilliSleep(200);

    // wake all the (remaining) threads up, so that they can exit
    CPPUNIT_ASSERT_EQUAL( wxCOND_NO_ERROR, condition.Broadcast() );

    // give them time to terminate (dirty!)
    wxMilliSleep(500);
}
示例#9
0
wxCondError wxConditionInternal::Broadcast()
{
    wxCriticalSectionLocker lock(m_csWaiters);

    while ( m_numWaiters > 0 )
    {
        if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
            return wxCOND_MISC_ERROR;

        m_numWaiters--;
    }

    return wxCOND_NO_ERROR;
}
示例#10
0
文件: misc.cpp 项目: beanhome/dev
    virtual ExitCode Entry()
    {
        //wxPrintf(wxT("Thread %lu has started running.\n"), GetId());
        gs_cond.Post();

        //wxPrintf(wxT("Thread %lu starts to wait...\n"), GetId());

        m_mutex->Lock();
        m_condition->Wait();
        m_mutex->Unlock();

        //wxPrintf(wxT("Thread %lu finished to wait, exiting.\n"), GetId());

        return 0;
    }
示例#11
0
wxCondError wxConditionInternal::Signal()
{
    wxCriticalSectionLocker lock(m_csWaiters);

    if ( m_numWaiters > 0 )
    {
        // increment the semaphore by 1
        if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
            return wxCOND_MISC_ERROR;

        m_numWaiters--;
    }

    return wxCOND_NO_ERROR;
}
示例#12
0
void wxThreadInternal::Resume()
{
    wxCHECK_RET( m_state == STATE_PAUSED,
                 wxT("can't resume thread which is not suspended.") );

    // the thread might be not actually paused yet - if there were no call to
    // TestDestroy() since the last call to Pause() for example
    if ( IsReallyPaused() )
    {
        // wake up Pause()
        m_semSuspend.Post();

        // reset the flag
        SetReallyPaused( false );
    }

    SetState( STATE_RUNNING );
}
示例#13
0
文件: misc.cpp 项目: beanhome/dev
void MiscThreadTestCase::TestDetached()
{
    static const size_t nThreads = 3;
    MyDetachedThread *threads[nThreads];

    size_t n;
    for ( n = 0; n < nThreads; n++ )
    {
        threads[n] = new MyDetachedThread(10, 'A' + n);
    }

    threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
    threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);

    for ( n = 0; n < nThreads; n++ )
    {
        CPPUNIT_ASSERT_EQUAL( wxTHREAD_NO_ERROR, threads[n]->Run() );
    }

    // wait until all threads terminate
    CPPUNIT_ASSERT_EQUAL( wxSEMA_NO_ERROR, gs_cond.Wait() );
}
示例#14
0
wxCondError wxConditionInternal::Wait()
{
    // increment the number of waiters
    IncrementAtomic( &m_numWaiters );

    m_mutex.Unlock();

    // a potential race condition can occur here
    //
    // after a thread increments nwaiters, and unlocks the mutex and before the
    // semaphore.Wait() is called, if another thread can cause a signal to be
    // generated
    //
    // this race condition is handled by using a semaphore and incrementing the
    // semaphore only if 'nwaiters' is greater that zero since the semaphore,
    // can 'remember' signals the race condition will not occur

    // wait ( if necessary ) and decrement semaphore
    wxSemaError err = m_semaphore.Wait();
    m_mutex.Lock();

    return err == wxSEMA_NO_ERROR ? wxCOND_NO_ERROR : wxCOND_MISC_ERROR;
}
示例#15
0
wxCondError wxConditionInternal::Broadcast()
{
    wxCriticalSectionLocker lock(m_csWaiters);

#if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */
#   pragma ivdep
#   pragma swp
#   pragma unroll
#   pragma prefetch
#   if 0
#       pragma simd noassert
#   endif
#endif /* VDM auto patch */
    while ( m_numWaiters > 0 )
    {
        if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
            return wxCOND_MISC_ERROR;

        m_numWaiters--;
    }

    return wxCOND_NO_ERROR;
}