|
I always just use CreateEvent().
hTimerEvent = ::CreateEvent(NULL, false, false, NULL);
and pass (LPTIMECALLBACK)hTimerEvent to ::timeSetEvent() with the TIME_CALLBACK_EVENT_SET timer
event type.
Mark
|
|
|
|
|
Mark Salsbery wrote: I always just use CreateEvent().
Strange, I can't get it to work for me. Here's the layout
I create the Event and the timer from my main thread, I launch a seperate thread which calls WaitForMultipleObjects(). I then call ResetEvent() and inform the main thread the evvent has occured. But! the event doesn't occur no matter what paramaters I call the various functions with.
Could this be some sort of thread related problem?
|
|
|
|
|
WalderMort wrote: I then call ResetEvent()...
Reset? It's a manual reset event then?
WaitForMultipleObjects() never returns?
|
|
|
|
|
I have tried both manual and auto resets, neither work. I have also tried named events, they don't work either. WaitForMultipleObjects() doesn't indicate that the event is set, but then it's on a 500ms timeout to prevent locking the handles.
Everything works perfectly if I use a callback function, but that's not what I want.
From MSDN:
"Any thread of the calling process can specify the event-object handle in a call to one of the wait functions.
So my code should be working.
|
|
|
|
|
Some sample code...
UINT wTimerRes = 0;
MMRESULT mmTimerId = 0;
HANDLE hTimerEvent = ::CreateEvent(NULL, false, false, NULL);
TIMECAPS tc;
if (::timeGetDevCaps(&tc, sizeof(TIMECAPS)) == TIMERR_NOERROR)
{
wTimerRes = min(max(tc.wPeriodMin, 1), tc.wPeriodMax);
::timeBeginPeriod(wTimerRes);
mmTimerId = ::timeSetEvent(500, wTimerRes, (LPTIMECALLBACK)hTimerEvent, (DWORD_PTR)0,
TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
}
int n = 0;
while (n < 10)
{
::WaitForSingleObject(hTimerEvent, INFINITE);
n++;
}
if (mmTimerId)
{
::timeKillEvent(mmTimerId);
mmTimerId = 0;
::timeEndPeriod(wTimerRes);
wTimerRes = 0;
}
::CloseHandle(hTimerEvent);
hTimerEvent = NULL;
|
|
|
|
|
Just an update. I never could get the multimedia timers to work with more than one event. I ended up changing the code slightly.
I now create an event for each timer just as before, but I create the timer using a callback function. Within this function I set the event ( which is what MMtimer is supposed to do! ). I then run a thread which waits on these events and does whatever the user intended.
|
|
|
|
|
hmmm beats me. I tested the code I posted before posting it.
Here's how I wait in many of my thread procs...maybe there's something that's different than
yours...
while (1)
{
#define EVENT_TIMER 0
#define EVENT_TERMINATE 1
HANDLE Events[] =
{
hTimerEvent,
hTerminateEvent
};
DWORD dwEventIndex = ::WaitForMultipleObjects(sizeof(Events) / sizeof(HANDLE),
Events, FALSE, INFINITE);
if (dwEventIndex == WAIT_FAILED)
{
break;
}
dwEventIndex -= WAIT_OBJECT_0;
if (dwEventIndex == EVENT_TERMINATE)
{
break;
}
... timer event occurred - do something
}
|
|
|
|
|
The only real difference is that I use dynamic arrays, but on watching through the debugger, the correct values are being passed in. Thinking that may be the problem, I instructed the thread to copy the handles to it's own 'stack based' array, the problem didn't go away.
I then thought that the events may be being set at exactly the same time ( Wait... returns only 1 index in such a case ) and tried a manual set and reset, no luck. Even with wait INFINITE for all objects.
I must try the same with other object like mutex's, it may be a bug within windows vista.
One question though, the docs say a timer is run in it's own thread. I set two timers and 1 worker thread. The 'task manager' states my exe has only 3 threads. So I'm guessing MMtimer creates a single thread to watch all timers, is this correct?
|
|
|
|
|
WalderMort wrote: I then thought that the events may be being set at exactly the same time
( Wait... returns only 1 index in such a case )
That's definitely a possibility. If you need to differentiate between which timer event occurred
then you'd have to use separate events instead of sharing one event. I would think sharing
an event would kind of negate the need for the precision of a multimedia timer anyway.
WalderMort wrote: I set two timers and 1 worker thread. The 'task manager' states my exe has only 3 threads.
So I'm guessing MMtimer creates a single thread to watch all timers, is this correct?
I know nothing about the internals of the multimedia timers, sorry I would guess that none
of the timer threads are in your/our process though (kernel?), so maybe they don't show up...
From this article: Results from a Latency Study of Windows NT[^]
"Multimedia timers are implemented by spawning a high-priority thread that sets a kernel timer
and then blocks. Upon awakening the thread executes a callback routine provided by the user,
schedules its next wakeup, and then goes back to sleep."
It's interesting that it's not working as advertised for you. I've never had any probs with the
multimedia timers but I do hope my software runs on Vista
Does the first code sample I posted work for you? That code can be inserted anywhere - it
doesn't need a separate thread.
Mark
|
|
|
|
|
I am currently working on a 2D shooter game, and I would like to be able to include enemy turrets that will be able to rotate towards the player to be able to fire at the player. The turrets have an angle variable, which stores which angle they are currently being rotated by (so which direction they're facing), and I want them to be able to track the player and determine which direction to turn to face the player the quickest. Let me attempt to explain this graphically
--------
Player
--------
--------
Turret -----> Current Firing Direction
--------
In this situation, assuming the player is 135 degrees from the turret, and the turret's rotation is 0, how can I make the turret understand that the best way to track the player is by rotating counterclockwise instead of clockwise? I have tried several methods, including attempts at using the dot products of the 2 vectors, etc. If anyone has any suggestions all help will be appreciated! Thanks!
-Steve
|
|
|
|
|
You could use the cross product[^]. To cut a long story short use this formula:
dir = x1.y2-x2.y1
Note that "." means multiply and only the sign of "dir" is of interest: +ve means anticlockwise and -ve clockwise, or the opposite if you're using a 4th quadrant coordinate system (which is probably the case here). (x1, y1) is the coordinates of the end of the turret on the firing ship, relative to the base of the turret. (x2, y2) is the point you're aiming for, relative to the base of the turret on the firing ship.
Steve
|
|
|
|
|
|
I recently formatted and reinstalled XP Pro on one of my machines and now my application that uses GDI+ for font rendereing does not display the text. I have searched MSDN and found a GDI+ redistributable but it says it is only for 2000 and that you should use the system-supplied one for XP.
Any idea why this doesn't appear to have been installed with XP and where I can get the file?
Thanks,
Dustin
|
|
|
|
|
Hi,
Im creating a server using UDP and IOCP.
I've red some articles about it and i understand the most of it ( the basic anyway. not saying im a IOCP master )
anyway, since i got a lot of ERROR_IO_PENDING returns when doing a WSASendTo or WSARecvFrom, i got myself wondering what hapends when i get this error. I know what it means but i dont quit seem to get or find any information about how to process it. What hapends when a send or recv function returns this and what is the best way of processing it?
Thanks already!
|
|
|
|
|
Most, if not all, of of your overlapped operations on a socket associated with an IOCP should
return this "error". It means that the overlapped operation was queued for processing by the
IOCP and when the operation is complete then one of the threads waiting on the IOCP (via
GetQueuedCompletionStatus()) will be released. When a thread receives the completion notification
(GetQueuedCompletionStatus() returns) then you can check if an error occurred. If the operation
was successful do whatever processing needs to be done (perhaps destroying the send/recv buffer,
returning it to a buffer pool, queuing up another overlapped operation, etc).
Any other error than ERROR_IO_PENDING means the operation was NOT queued so you'll never get
a completion notification. In other words, the operation failed immediately.
Mark
|
|
|
|
|
ok, i see that makes it all clear. In a related question, when i have multiple threads and when i do a WSASendTo or whatever, it returns -1 so i use WSAGetLastError(). to retrieve the error. Does WSAGetLastError() returns the last error associated with that specific thread, or could it happen that 2 threads at the same time store an error and that i might retrieve an error from another thread with WSAGetLastError()? ( doest seems likely but who knows)
|
|
|
|
|
Yes WSAGetLastError() returns the error code for the last socket API called on the calling thread.
Mark
|
|
|
|
|
And....especially for overlapped calls, you should check the error EVERY time the API indicates
an error. Otherwise there's no way to effectively manage the overlapped buffers.
Mark
|
|
|
|
|
ok, thnx
|
|
|
|
|
Hi,
Knowing that it is possible to instantiate a new object at runtime with CRuntime class, I was wondering if it would be possible to allow a user of an application to create a new variable at runtime.
For example the user inputs the name of the variable from within an edit control and selects the type of the variable from a ComboBox.
Finaly the new variables and their values could be saved when the user exits the application.
Is there a possibility to do it? If yes could you please tell me how to do it or where I can get further documentation?
With many for your help.
|
|
|
|
|
If MFC...
Check out the CArchive class. If you implement the classes as serializable then you can save and
create from saved objects of the classes.
Serialization in MFC[^]
|
|
|
|
|
you cannot do this in C++.
BUT
You could create a map containing the name of the variable and a pointer to a user defined type :
for example in very pseudo-c++code :
class MyTypes
{
};
class MyIntType : public MyTypes
{
int m_iValue;
}
class MyVariable
{
MyType* m_pType;
std::string m_sVariableName;
}
std::map< std::string, MyVariable* > myVariableMap;
MyIntType myValue = new MyIntType( 123 );
myVariableMap.insert( "myIntVariable", new MyVariable( "myIntVariable", myValue ));
And then when lookup in the map to find the variable ( by name ).
I'm sure you could add a template somewhere in there, as well as operators on MyVariable to manage your series of custom types.
|
|
|
|
|
Arris7 wrote: For example the user inputs the name of the variable from within an edit control and selects the type of the variable from a ComboBox.
This is not possible in c++.
Nobody can give you wiser advice than yourself. - Cicero
ப்ரம்மா
|
|
|
|
|
Hi there,
I need to add the code in C++ to an sim card reader application.
I will add a button into existing application but I need the code that will save sim card numbers as text file.
Many thanks,
Regards
Tonny
|
|
|
|
|
I used to use the function to try and determine if a program was running as a system service (versus a userland program)... It seems to have fallen of the face of the earth.
I have a work around (GetTokenInformmation wich requires a user defined buffer), but I'm suprised at how it just disappeared.
Even Richter and Clark discuses it in their book Programming Server-Side Applications for Microsoft Windows 2000[^]
Jeff
BOOL bResult = FALSE;
SID_IDENTIFIER_AUTHORITY siaAuthority = SECURITY_NT_AUTHORITY;
PSID psidLocalSystem = NULL;
HANDLE hToken = INVALID_HANDLE_VALUE;
VOID* lpTokenInformation = NULL;
TOKEN_USER* lpUserToken = NULL;
__try {
if( FALSE == AllocateAndInitializeSid( &siaAuthority,
1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0, &psidLocalSystem ) )
{ __leave; }
if( FALSE == IsValidSid( psidLocalSystem ) ) { __leave; }
if( FALSE == OpenProcessToken( GetCurrentProcess(),
TOKEN_QUERY | TOKEN_QUERY_SOURCE, &hToken ) )
{ __leave; }
if( INVALID_HANDLE_VALUE == hToken )
{ __leave; }
DWORD dwNeeded = 0;
GetTokenInformation( hToken, TokenUser, NULL, 0, &dwNeeded );
if( 0 == dwNeeded ) { __leave; }
lpTokenInformation = HeapAlloc( GetProcessHeap(), 0, dwNeeded );
if( NULL == lpTokenInformation ) { __leave; }
assert( dwNeeded < 0x7FFF8 );
DWORD dwSize = dwNeeded;
if( FALSE == GetTokenInformation( hToken,
TokenUser, lpTokenInformation, dwSize, &dwNeeded ) )
{ __leave; }
lpUserToken = static_cast<TOKEN_USER*>( lpTokenInformation );
if( FALSE == IsValidSid( lpUserToken->User.Sid ) ) { __leave; }
if( TRUE == EqualSid( psidLocalSystem, lpUserToken->User.Sid ) )
{ bResult = TRUE; }
}
__finally { }
if( NULL != psidLocalSystem )
{ FreeSid( psidLocalSystem ); }
if( NULL != hToken )
{ CloseHandle( hToken ); }
if( NULL != lpTokenInformation )
{ HeapFree( GetProcessHeap(), 0, lpTokenInformation ); }
return bResult;
|
|
|
|
|