views:

155

answers:

2

I need to create a C++/CLI mixed assembly that can schedule future calls into a native DLL with millisecond accuracy.

This will, of course, mean setting a timer (what kind?) for a millisecond or three beforehand, then spinning until the moment and calling the native DLL function.

Based on what I've read, I would guess that the callback that the timer calls will need to be native to make sure there are no thunks or GC to delay handling the timer callback.

Will the entire thread or process need to be native and CLR-free, though, or can this be done just as accurately with #pragma unmanaged or setting one file of the assembly to compile as native?

If so, how?

If there is indeed no way to do this in mixed-mode C++/CLI, what would be the easiest way to set up an app/thread (ie, DLL or exe?) to handle it and to get the data back and forth between the native and managed threads/apps?

+1  A: 

It can not be done in windows at all - sorry. Get an OS that fits your requirements.

  • Normal timers in windows havve a 10ms accuracy.
  • Even if you get it working withh high performance timers, there are no accuracy guarantees in windows that the call will be honoured within a specific time - your 1ms call may come in 5ms late.

What you need / seem to need is a real time operating system.

TomTom
This hardware only has drivers for Windows.In native Windows-land, you can get 99.99% reliability (better than I need) at 1ms accuracy. There are examples all over. I've run one and gotten zero failures while I was using the computer all day.THE QUESTION IS ABOUT HOW TO BRING THAT IN TO .NET WITHOUT LETTING .NET GET IN THE WAY OF THE CRITICAL SECTION.I want to know how to write the callback such that no thunks or GCs occur between the timer going off and the DLL being called.
A Student at a University
Still out of luck. For the GC - set the non-blocking GC. Besides that there is nothing else I am aware .NET puts into your way.
TomTom
+3  A: 

You do need the entire thread to be CLR-free. As soon as any managed code runs on the thread, it will get added to the CLR's list of threads to suspend during collection.

Your last question, though, suggests that you have no clue about multithreading. There is no correspondence between threads and DLLs. A DLL can have many threads, and each thread can run code from many DLLs (in fact, always does, if you count Windows DLLs). You're also not using the phrase "critical section" in the usual way.

A mixed-mode C++/CLI assembly can contain a native-only thread (start it using the native CreateThread call, passing a native thread procedure, and don't call any managed code directly or indirectly from that thread). Your life will be a little easier if you write the code for the native thread in one or more files set to compile without /clr, not having managed code visible makes it easier to avoid calling it, although beware of function pointers which might be wrapping managed delegates.

Beyond that, use lock-free synchronization, e.g. SList, or your native thread could end up waiting for a lock held on a mixed-mode thread which has been suspended for garbage collection. Among other things this means not using any of the standard shared allocators, because they use locking internally. Some lock-free allocators do exist though.

EDIT: Function pointers which wrap managed delegates are created by calling Marshal::GetDelegateForFunctionPointer. After that, they act just like pointers to native functions (it is possible to tell them apart) and using the function call operator on such a pointer will cause managed code to run on the sensitive thread. In most cases this won't be a problem, just make sure if you are using delegates as a shortcut to produce callbacks to managed code, that you do so from the mixed thread and not the one you intend to be native-only.

In general, you'll probably want some sort of purely native message passing scheme to exchange data. The mixed thread can make whatever native calls are necessary, you can mix native and managed code on all your other threads, just keep the time-sensitive one native-only.

All thunking should occur on the mixed thread, and it won't delay the time-sensitive native thread unless the mixed thread is holding a lock that the native thread needs. Hence my suggestion to use non-locking data exchange.

Ben Voigt
So one can make a thread CLR-free in a mixed assembly, and that thread can be uninhibited by the managed/mixed threads? (Looking for others to agree or disagree, and to explain how further.)Are there automatic "function pointers wrapping managed delegates"? How do I avoid accidentially using them?I am aware that DLLs map in as part of the loader, and that threads can use code from many DLLs. The question is best-practice: Whether to make a process for this (and, if so, how best to IPC to it) or to make a native-only thread (and how to code the calls to it).
A Student at a University
I'm worried about how to interop into the thread or IPC into the process without thunking during the time-sensitive moment. (Apologies for calling that a critical section when I didn't mean lock contention.)
A Student at a University