Click here to Skip to main content
15,921,837 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
GeneralRe: ON_UPDATE_COMMAND_UI wont update my menu text (in dialog based application) Pin
Michael Dunn14-Jun-03 6:32
sitebuilderMichael Dunn14-Jun-03 6:32 
GeneralRe: ON_UPDATE_COMMAND_UI wont update my menu text (in dialog based application) Pin
tfiner11-Apr-12 8:00
tfiner11-Apr-12 8:00 
GeneralAsynchronies dial up connection Pin
no_body6913-Jun-03 18:55
no_body6913-Jun-03 18:55 
GeneralRe: Asynchronies dial up connection Pin
Kuniva15-Jun-03 4:30
Kuniva15-Jun-03 4:30 
QuestionApplication causing Windows clock drift? Pin
Gavin Stark13-Jun-03 18:05
Gavin Stark13-Jun-03 18:05 
AnswerRe: Application causing Windows clock drift? Pin
John Aldrich13-Jun-03 18:46
John Aldrich13-Jun-03 18:46 
GeneralRe: Application causing Windows clock drift? Pin
Gavin Stark13-Jun-03 19:13
Gavin Stark13-Jun-03 19:13 
GeneralRe: Application causing Windows clock drift? Pin
Gavin Stark16-Jun-03 17:54
Gavin Stark16-Jun-03 17:54 
Turns out this problem only seems to occur on dual processor or dual processor CAPABLE machines. I have generated some sample code which exhibits the problem. If anyone can tell me why this happens or if there is a "workaround" which doesn't involve changing code, I'd be grateful. I do know that one change that makes this work is calling timeBeginPeriod/timeEndPeriod ONCE per instance of the application rather than repeatedly, but I can't change the code in question.

Sample code at:
http://gstark.home.mindspring.com/MultiMediaTimerBug.cpp [^]


//
//
//  Time slip test program which demonstrates an issue with multimedia timers
//  on multiprocessor kernel Windows 2000.  This program creates several threads which
//  are all creating and destroying a Win32 Multimedia Timer.  After running
//  for some time (its better to just leave the computer alone, no mouse moves, etc.)
//  the Windows clock will have drifted FORWARD in time.  This can be checked
//  by doing a sync with an "atomic clock" program before and maybe 15 minutes into
//  the run.
//
//

// link with win multimedia
#pragma comment( lib, "Winmm.lib" )


#include <process.h>
#include <windows.h>
#include <stdio.h>

// Sleep time
const UINT kSleepyTimeMilliseconds = 300;

// Empty timer callback proc
void CALLBACK    Win32MultiMediaTimerProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
}

// Thread proc to test multimedia timer
//==================================================================================================
unsigned __stdcall    Win32_MyThreadProcStdC(void* threadInput_i)
{
    while( TRUE )
    {
        MMRESULT    result;

        // get the capabilities of the multimedia device
        TIMECAPS timeCapabilities;
        result = ::timeGetDevCaps(&timeCapabilities,sizeof(timeCapabilities));
        if (result != TIMERR_NOERROR)
            return 0;

        // set the minimum resolution of the timer
        //
        //    NOTE: We want to be capable of 1 millisecond resolution.
        //
        UINT myWin32TimerResolution = timeCapabilities.wPeriodMin;
        if (timeCapabilities.wPeriodMax < myWin32TimerResolution)
            myWin32TimerResolution = timeCapabilities.wPeriodMax;
        if (myWin32TimerResolution < 1)
            myWin32TimerResolution = 1;

        // Begin the timer
        result = ::timeBeginPeriod(myWin32TimerResolution);

        // define the timer options
        register UINT timerOptions = TIME_CALLBACK_FUNCTION
                                   | TIME_PERIODIC;

        // create the timer
        MMRESULT myWin32MultiMediaTimerID = ::timeSetEvent(
                                                  (UINT)500,                    // delay
                                                  myWin32TimerResolution,        // timer resolution
                                                  Win32MultiMediaTimerProc,        // callback
                                                  (DWORD)0,                        // user data
                                                  timerOptions                    // options
                                                 );

        DWORD lastWin32Error    = ::GetLastError();
        
        // I'm not sure if this I/O is necessary to produce the time slip, but here it is anyway
        FILE* f = fopen( "trashFile","w");
        if( f )
        {
            fprintf(f, "trash\n" );
            fclose(f);
        }

        // Sleep for a while, maybe to let the clock drift happen?
        ::Sleep( kSleepyTimeMilliseconds );
        
        for( UINT i = 0; i < kSleepyTimeMilliseconds; i++ )
        {
            ::Sleep( 0 );
        }

        result            = ::timeKillEvent( myWin32MultiMediaTimerID );
        lastWin32Error    = ::GetLastError();
        UINT    killRetryCount    = 3;

        // Since we are specifying that we are using TIME_KILL_SYNCHRONOUS, we should
        // not have to do this work, but it is here for additional safety.
        // If we have an error, we will try a number of times to 
        // shut down the timer
        while(        ( result != TIMERR_NOERROR )
                &&  ( killRetryCount > 0 ) )
        {
            // Yield the CPU to allow the thread that may be holding this timer resource
            ::Sleep(0);

            result            = ::timeKillEvent( myWin32MultiMediaTimerID );
            lastWin32Error    = ::GetLastError();

            // If we received something other than "no error", and the last error
            // is that we have somehow already terminated the timer, set
            // our success state to TIMERR_NOERROR
            if(        ( result != TIMERR_NOERROR )
                &&  ( lastWin32Error == ERROR_ALREADY_EXISTS ) )
            {
                result            = TIMERR_NOERROR;
                lastWin32Error    = 0;
            }

            // Decrement our retry count until we have exhausted all retries
            killRetryCount--;
        }

        switch (result)
        {
            case TIMERR_NOERROR:
                // nothing to do here...
                break;

            case MMSYSERR_INVALPARAM:
                // return a failure
                return 0;

            case TIMERR_NOCANDO:
                break;
                
            default:
                // we didn't expect this
                break;
        }

        // terminate the time services
        result = ::timeEndPeriod(myWin32TimerResolution);

        ::Sleep( kSleepyTimeMilliseconds );
    }

}

// Creates a number of threads to test the Win32 MultiMedia clock drift problem.
void ThreadTest()
{
    const UINT kNumberThreads = 10;

    // Create a bunch of threads that will create and destroy a lot of timers
    for( UINT i = 0; i < kNumberThreads; i++ )
    {

        // create the thread
        unsigned threadID;
        const unsigned long threadResult = _beginthreadex(
                                                          NULL,                        // security (NULL ==> default)
                                                          0,                        // stack size
                                                          Win32_MyThreadProcStdC,    // start address
                                                          NULL,                        // argument list
                                                          0,                        // init flags
                                                          &threadID                    // resultant thread ID
                                                         );
    }
    
    // Once the threads are going we will quietly wait for the program to be killed.
    while( TRUE )
    {
        ::Sleep( 1000 );
    }
}

//==================================================================================================
int    main(int               argumentCount_i,
         const char* const argumentValueArray_i[])
{
    ThreadTest();

    // return a success
    return 0;
}

QuestionHow I can access an external MS Access database (.mdb) Pin
ATC13-Jun-03 16:48
ATC13-Jun-03 16:48 
AnswerRe: How I can access an external MS Access database (.mdb) Pin
John M. Drescher13-Jun-03 17:35
John M. Drescher13-Jun-03 17:35 
GeneralRe: How I can access an external MS Access database (.mdb) Pin
ATC14-Jun-03 4:35
ATC14-Jun-03 4:35 
GeneralHiding Mainframe without flicker Pin
pranavamhari13-Jun-03 15:47
pranavamhari13-Jun-03 15:47 
QuestionHow to get a sub-member's pointer Pin
FlyingDancer13-Jun-03 15:43
FlyingDancer13-Jun-03 15:43 
AnswerRe: How to get a sub-member's pointer Pin
John M. Drescher13-Jun-03 15:55
John M. Drescher13-Jun-03 15:55 
GeneralRe: How to get a sub-member's pointer Pin
FlyingDancer13-Jun-03 16:02
FlyingDancer13-Jun-03 16:02 
GeneralRe: How to get a sub-member's pointer Pin
Tim Smith13-Jun-03 16:21
Tim Smith13-Jun-03 16:21 
GeneralRe: How to get a sub-member's pointer Pin
Ryan Binns14-Jun-03 4:50
Ryan Binns14-Jun-03 4:50 
AnswerRe: How to get a sub-member's pointer Pin
Michael Dunn13-Jun-03 16:33
sitebuilderMichael Dunn13-Jun-03 16:33 
GeneralRe: How to get a sub-member's pointer Pin
FlyingDancer13-Jun-03 19:14
FlyingDancer13-Jun-03 19:14 
GeneralRe: How to get a sub-member's pointer Pin
Michael Dunn13-Jun-03 19:22
sitebuilderMichael Dunn13-Jun-03 19:22 
GeneralRe: How to get a sub-member's pointer Pin
Toni7813-Jun-03 19:27
Toni7813-Jun-03 19:27 
GeneralRe: How to get a sub-member's pointer Pin
John M. Drescher14-Jun-03 4:42
John M. Drescher14-Jun-03 4:42 
AnswerRe: How to get a sub-member's pointer Pin
Brian Delahunty14-Jun-03 0:39
Brian Delahunty14-Jun-03 0:39 
GeneralRe: How to get a sub-member's pointer Pin
FlyingDancer14-Jun-03 1:12
FlyingDancer14-Jun-03 1:12 
GeneralRe: How to get a sub-member's pointer Pin
Brian Delahunty14-Jun-03 1:21
Brian Delahunty14-Jun-03 1:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.