How to flush events?
Moderator: Moderators
-
- Posts: 20
- Joined: Tue Mar 11, 2008 10:36 pm
How to flush events?
If my operation takes an 8th of a second to complete, then by the end of the first event i've accumulated dozens of events in the que, which now must play out one at a time.
To see this problem, open the 3DxValuesCarbon example, and change this line:
line 149: from this:
----------------
TdxComputeAxes(msg->axis);
----------------
to this:
----------------
#define kMicroSecPerSec 1000000
TdxComputeAxes(msg->axis);
usleep(0.25 * kMicroSecPerSec);
----------------
Now, when you run, twiddle the cap and let go --> it takes forever for the events to catch up to "now"
So what I'd like to do is this:
----------------
#define kMicroSecPerSec 1000000
TdxComputeAxes(msg->axis);
usleep(0.25 * kMicroSecPerSec);
ConnexionControl(kConnexionCtlFlushEvents, 0, &resultI);
----------------
how do i do this??
or: how do i correctly discard all the events except for the one happening RIGHT NOW ?
To see this problem, open the 3DxValuesCarbon example, and change this line:
line 149: from this:
----------------
TdxComputeAxes(msg->axis);
----------------
to this:
----------------
#define kMicroSecPerSec 1000000
TdxComputeAxes(msg->axis);
usleep(0.25 * kMicroSecPerSec);
----------------
Now, when you run, twiddle the cap and let go --> it takes forever for the events to catch up to "now"
So what I'd like to do is this:
----------------
#define kMicroSecPerSec 1000000
TdxComputeAxes(msg->axis);
usleep(0.25 * kMicroSecPerSec);
ConnexionControl(kConnexionCtlFlushEvents, 0, &resultI);
----------------
how do i do this??
or: how do i correctly discard all the events except for the one happening RIGHT NOW ?
Hi Dave,
It's good to see that you are tackling this. You'll have a lot of happy users.
I'm not familiar with the sample Mac code. I guess I'll have to boot into OS-X and look at it. Are you telling me that our sample code doesn't demonstrate any sort of real-time programming considerations? That might explain a lot...
What we usually suggest is to eat all the events from the queue each time you find any events. It is up to you whether you want to A) accumulate, B) accumulate and average, or C) just use the last available event. I tend to favor C since it represents closest to "now" and I really don't care what happened before.
Our sample code should at least mention, if not implement, this.
Jim
It's good to see that you are tackling this. You'll have a lot of happy users.
I'm not familiar with the sample Mac code. I guess I'll have to boot into OS-X and look at it. Are you telling me that our sample code doesn't demonstrate any sort of real-time programming considerations? That might explain a lot...
What we usually suggest is to eat all the events from the queue each time you find any events. It is up to you whether you want to A) accumulate, B) accumulate and average, or C) just use the last available event. I tend to favor C since it represents closest to "now" and I really don't care what happened before.
Our sample code should at least mention, if not implement, this.
Jim
-
- Posts: 20
- Joined: Tue Mar 11, 2008 10:36 pm
By that reaction, I'm assuming there is no way to:
I'll look at the API and discuss with the guy that wrote it, or someone more familiar with it.
AFAIK our SDK is just a thin wrapper over the standard Apple device event system. The data comes through the standard API.
Code: Select all
if (wokenForEventArrival)
{
while (ConnexionReadEvent(&event) == EVENT_WAS_READ)
{
useThisEvent = event;
}
}
DoViewMath(useThisEvent);
AFAIK our SDK is just a thin wrapper over the standard Apple device event system. The data comes through the standard API.
Last edited by jwick on Sat Apr 07, 2012 6:47 am, edited 1 time in total.
-
- Posts: 20
- Joined: Tue Mar 11, 2008 10:36 pm
-
- Posts: 20
- Joined: Tue Mar 11, 2008 10:36 pm
Hi Dave,
We have a couple of suggestions.
1) You can look at the time stamps of the messages as they come in and throw them out if the timestamp is too old. IOW, don't call TdxComputeAxes and all the time consuming operations that entails. You will get a more recent event on the next iteration in your main msg loop.
2) You can put the event gathering into another thread. We ship an example that shows how to do this. That thread would just do the event compression, then signal the main thread that controls the view when the last event is read.
In either case, be careful to not lose the all-zero event that tells you the user has let go of the device. This is often useful information to have to signal a more detailed refresh of the view.
I was also informed that there may be some code around your code base from experiments with this same API from a few years back. That effort was abandoned.
Jim
We have a couple of suggestions.
1) You can look at the time stamps of the messages as they come in and throw them out if the timestamp is too old. IOW, don't call TdxComputeAxes and all the time consuming operations that entails. You will get a more recent event on the next iteration in your main msg loop.
2) You can put the event gathering into another thread. We ship an example that shows how to do this. That thread would just do the event compression, then signal the main thread that controls the view when the last event is read.
In either case, be careful to not lose the all-zero event that tells you the user has let go of the device. This is often useful information to have to signal a more detailed refresh of the view.
I was also informed that there may be some code around your code base from experiments with this same API from a few years back. That effort was abandoned.
Jim
-
- Posts: 20
- Joined: Tue Mar 11, 2008 10:36 pm
i was afraid you might say that. bummer.
1) if there is a precise definition of "too old" this might work, but it'd be far too easy to process events you don't need to, or actually miss the last event that you actually want. Due to the realtime nature of whatever calculation we're doing, every event may seem "too old".
2) that's too much work, i have to be done with this.
and yes, the old code is where i started from. i see now that this is the problem they ran into. we have way too many threads now already and have to really justify creating a new one, which can slow down rendering.
i'm amazed that there is no simple, cross platform command for your API that says "flush everything", or a way to say "only hand me the most recent event if there are more than one in the que". this is really a requirement for simple adoption.
1) if there is a precise definition of "too old" this might work, but it'd be far too easy to process events you don't need to, or actually miss the last event that you actually want. Due to the realtime nature of whatever calculation we're doing, every event may seem "too old".
2) that's too much work, i have to be done with this.
and yes, the old code is where i started from. i see now that this is the problem they ran into. we have way too many threads now already and have to really justify creating a new one, which can slow down rendering.
i'm amazed that there is no simple, cross platform command for your API that says "flush everything", or a way to say "only hand me the most recent event if there are more than one in the que". this is really a requirement for simple adoption.
The device delivers data at approximately 60Hz. I'd say that anything older than 1/60 of a second ago, that does not have all-zero values, will shortly be followed up by another event. If the values are all-zero, the next event would be the next time the user touches the cap.davecotter wrote:i was afraid you might say that. bummer.
1) if there is a precise definition of "too old" this might work, but it'd be far too easy to process events you don't need to, or actually miss the last event that you actually want. Due to the realtime nature of whatever calculation we're doing, every event may seem "too old".
This isn't our API nor functionality. These are just simple wrappers over the OS-X platform. I do see where this is a place we could try to improve the Apple API, though. I am sure you are correct, that this sort of thing hurts us, preventing others from incorporating support for the products. We did provide a solution for this on Windows. I will look into a better solution for OS-X. The failure of this project should help me to get resources to provide a better solution.davecotter wrote:i'm amazed that there is no simple, cross platform command for your API that says "flush everything", or a way to say "only hand me the most recent event if there are more than one in the que". this is really a requirement for simple adoption.
-
- Posts: 20
- Joined: Tue Mar 11, 2008 10:36 pm
>> simple, cross platform command for your API that says "flush everything"
> This isn't our API nor functionality.
sorry if i wasn't clear. i was asking you to provide such functionality in both SDK's, not that i expected it to exist in the OS.
> We did provide a solution for this on Windows
interestingly i'm not seeing the same performance hit on windows using the messaging API.
do you mean the "SI_AVERAGE_EVENTS" flag? if that does what i think it does, then yes, i'd love to have that on the mac. but i'd be satisfied with just "give me the most recent event, throwing out all previous ones".
as i said in my original post, you could implement this:
> ConnexionControl(kConnexionCtlFlushEvents, 0, &resultI);
> This isn't our API nor functionality.
sorry if i wasn't clear. i was asking you to provide such functionality in both SDK's, not that i expected it to exist in the OS.
> We did provide a solution for this on Windows
interestingly i'm not seeing the same performance hit on windows using the messaging API.
do you mean the "SI_AVERAGE_EVENTS" flag? if that does what i think it does, then yes, i'd love to have that on the mac. but i'd be satisfied with just "give me the most recent event, throwing out all previous ones".
as i said in my original post, you could implement this:
> ConnexionControl(kConnexionCtlFlushEvents, 0, &resultI);
-
- Posts: 20
- Joined: Tue Mar 11, 2008 10:36 pm
Note that the forums suggest you use "clock_get_uptime" or "mach_absolute_time", but the correct function is "UpTime()".
Code: Select all
#define kNanoSecondsPerSecond 1000000000
#define kMilliSecondsPerSecond 1000
#define kNanoSecondsPerMilli (kNanoSecondsPerSecond / kMilliSecondsPerSecond)
static bool IsMostRecentMessage(UInt64& messageT)
{
UInt64 dur_message_nanoT(UnsignedWideToUInt64(
AbsoluteDeltaToNanoseconds(UpTime(), UInt64ToUnsignedWide(messageT))));
UInt64 dur_message_milliT(dur_message_nanoT / kNanoSecondsPerMilli);
UInt64 dur_tick_milliT(kMilliSecondsPerSecond / 60);
bool recentB = dur_message_milliT <= dur_tick_milliT;
return recentB;
}
Right. This is indeed the correct issue. Thanks for pointing it out.davecotter wrote:apparently, see enhancement request 4503
I added a reference to this thread in the issue tracker.
Like jwick stated above, the correct way to handle accumulated events is to filter them before calling the application back. The ball's on our side of the court.
Re: How to flush events?
3Dconnexion has released a driver update that addresses bug 4503. Version 10.2.2 of 3DxWare 10 was published on May 18, 2015 (yesterday). Your application will need to "weak link" to the driver framework (a "strong" link will lead to problem eventually as it may disconnect the driver from the loaded code in the application).