views:

129

answers:

3

I have an array of Win32 event handles that I'm waiting on using WaitForMultipleObjects(). This returns the index in the array of events that triggered but what I need to know is the name of the event. I've been looking through MSDN and can't see anything to do this.

Basically I have a class that monitors the registry through events using RegNotifyChangeKeyValue() for a defined period of time but before it starts other classes register there interest in keys and values. I then wait on a separate thread and report back the name of the keys that have been modified. The event name is the key that the event is for and I don't know until runtime how many of these there will be or what they will be called. I don't want to create one thread per key as it's not very performant.

Does anyone know how to get the event name or a better way of doing this?

+1  A: 

Personally I wouldn't do it that way. Create your own mapping (std::map?) between event and key name and then do your own lookup when an event is signalled.

Len Holgate
That's my current plan. It just doesn't seem very elegant
L2Type
For this situation, a map is probably overkill -- a vector should work just fine. Just put the names in the vector in the same order as the corresponding handles in the array you pass to WMFO. Then the index that's returned from WMFO will also act as an index into the names.
Jerry Coffin
A map would be better than manually keeping two arrays aligned. The overhead is insignificant.
Kieveli
What difficulty would there be in keeping the two aligned? With typical code, it'd happen automatically -- for example, you'd use a vector for each, and when you get a name to watch, use push_back to add it to the vector of names, and then use push_back to add the handle to the vector of handles. Likewise, when you remove one, you'd normally use the same technique (e.g. remove/erase) for both, again automatically maintaining the same order.
Jerry Coffin
Jerry, good spot. I agree, the vector of names should be easy to keep in sync with the vector of handles. One thing I'd add is that personally I'd have an extra event as the first event to wait on, this would be a 'please stop waiting NOW' event that can be used when you want to shutdown or destroy the class that encloses all of this.
Len Holgate
It's no problem when you first add it if you're careful. It's after the third person has modified the class, made one of the vectors publicly accessable, and then allowed some other class to modify it directly. A map is more straight-forward.
Kieveli
@Len, Yes I have an event to stop listening and it's always in position 0.@Jerry, I used the twin vector approach. I had it mind before posting the question but it seems a strange ommision that you can't get the event name.
L2Type
@Kieveli You kick them when they make it publically accessible; you can use that excuse for any poor design decision...@DotNetWill - event (and other kernel object) names aren't meant for that kind of usage. Don't fight it.
Len Holgate
A: 

Normally the name of an event is used to call OpenEvent() to get the Handle. This way, you don't need to communicate a handle at runtime, but instead settle on a naming convention for the name of the event.

I can think of three ways to do this:

  • Loop over all hard-coded event names and call OpenEvent()
  • Save the handles and names in an std::map
  • Create a class to store your handles and names (possibly in an std::map), and write methods to quickly get a name from a handle.

Are you deciding what actions to take based on the name of the event? An 'if else if' statement that checks the names of the handles one-by-one to determine what action to take? This kind of scenario usually leads me to consider inheritance as a potential solution. Bear with me for a bit.

What if you create a base class, say EventAction. This has a handle to an event, and a virtual member function go_go_commandos(). You derive from it for each 'event' that has an action to be taken, and implement the action in the go_go_commandos() method of each deriving class.

Now what you need is a container so you can say actionlist->GetEventAction( handle )->go_go_commandos().

Did that help at all?

Kieveli
I see what you're getting at but what I'm trying to do is have a registry watcher for values only and have multiple objects that want to know about changes to values under a key. So I need to get watch the relevant keys then work out what values changed then call into only the interested objects. If that makes sense. Win32 doesn't offer this only to watch Keys.
L2Type
I guess I still don't see why you would want to do a lookup on the name of the event given the handle.
Kieveli
DO NOT use the name available in OpenEvent(). This makes your object shared across processes, using that name. With an lpsa of NULL, your object will be wide open to manipulation and you will have a security hole. Len Holgate's map idea is ultra simple, I would go that route.
Heath Hunnicutt
@Kieveli It was just the way my mind was working at the time, the map/vector approach is a better one.@Heath. Thanks, I didn't know that and have changed it now :)
L2Type
+1  A: 

You could probably do it with undocumented NT stuff, maybe NtQueryObject(handle,ObjectNameInformation,....)

Anders
useful to know that you can do this; but I really wouldn't want to...
Len Holgate