Esempio n. 1
0
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() );
}
Esempio n. 2
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;
}
Esempio n. 3
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();
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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() );
}
Esempio n. 6
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;
}