How to flush events?

Post questions, comments and feedback to our 3Dconnexion Mac Development Team.

Moderator: Moderators

How to flush events?

Postby davecotter » Thu Apr 05, 2012 4:20 pm

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 ?
davecotter
 
Posts: 19
Joined: Tue Mar 11, 2008 10:36 pm

Postby jwick » Fri Apr 06, 2012 7:22 am

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
jwick
Moderator
Moderator
 
Posts: 1769
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA

Postby davecotter » Fri Apr 06, 2012 9:36 am

we suggest is to eat all the events from the queue each time you find any events

Yes, but HOW?
davecotter
 
Posts: 19
Joined: Tue Mar 11, 2008 10:36 pm

Postby jwick » Fri Apr 06, 2012 10:01 am

By that reaction, I'm assuming there is no way to:

Code: Select all
if (wokenForEventArrival)
{
   while (ConnexionReadEvent(&event) == EVENT_WAS_READ)
   {
      useThisEvent = event;
   }
}

DoViewMath(useThisEvent);

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.
Last edited by jwick on Sat Apr 07, 2012 6:47 am, edited 1 time in total.
jwick
Moderator
Moderator
 
Posts: 1769
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA

Postby davecotter » Fri Apr 06, 2012 4:47 pm

There is no "ConnexionReadEvent()" API., and the type of NSEvent is not documented, so i do not see any way to flush them. I need this info to continue, i only have one more working day to show i completed it, else it will be abandoned.
davecotter
 
Posts: 19
Joined: Tue Mar 11, 2008 10:36 pm

Postby davecotter » Mon Apr 09, 2012 10:11 am

i sure hope you can get an answer for me today. as you say, lots of people would be happy to have this built in. but without the ability to say "only give me the most recent event", it's not going to work.
davecotter
 
Posts: 19
Joined: Tue Mar 11, 2008 10:36 pm

Postby jwick » Mon Apr 09, 2012 12:28 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
jwick
Moderator
Moderator
 
Posts: 1769
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA

Postby davecotter » Mon Apr 09, 2012 12: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.
davecotter
 
Posts: 19
Joined: Tue Mar 11, 2008 10:36 pm

Postby jwick » Mon Apr 09, 2012 1:53 pm

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".
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'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.
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.
jwick
Moderator
Moderator
 
Posts: 1769
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA

Postby davecotter » Mon Apr 09, 2012 2:12 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);
davecotter
 
Posts: 19
Joined: Tue Mar 11, 2008 10:36 pm

Postby davecotter » Mon Apr 09, 2012 2:51 pm

apparently, see enhancement request 4503
davecotter
 
Posts: 19
Joined: Tue Mar 11, 2008 10:36 pm

Postby davecotter » Thu Apr 12, 2012 11:17 am

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;
}
davecotter
 
Posts: 19
Joined: Tue Mar 11, 2008 10:36 pm

Postby ngomes » Thu Apr 12, 2012 12:45 pm

davecotter wrote:apparently, see enhancement request 4503

Right. This is indeed the correct issue. Thanks for pointing it out.

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.
ngomes
Moderator
Moderator
 
Posts: 1656
Joined: Mon Nov 27, 2006 7:22 am
Location: EU


Return to Developer's Forum for Mac OS X

Who is online

Users browsing this forum: No registered users and 1 guest