From: David Ching on
"JRGlide" <JRGlide(a)discussions.microsoft.com> wrote in message
news:EEB5EE8A-1F6A-4C3C-9473-045EBB640787(a)microsoft.com...
> Thank you. You are right that MATLAB loads a DLL and then calls another
> DLL
> which displays the data. In case it matters, the viewing program is an
> application that I converted into a DLL, so it has its own CWinApp, menus,
> CView, etc. In fact, you may have been the one who helped me develop it
> several years ago.
>
> My question about your approach is that I alway read on this forum that
> the
> GUI should always be in the application and never in a thread - that only
> processing should be done is a separate thread. So why is this different?
>

It is a good general rule to keep all UI on the main thread. But it is safe
to create and access additional windows on a separate thread. This is
especially true in this case where the MATLAB window is disabled while yours
is active, so there is no chance the user can simultanously mix the two.
The rule is the window must be accessed only from the thread it is created
in. In the new thread, make sure you init OpenGL and OLE if necessary.

-- David


From: David Ching on
"David Ching" <dc(a)remove-this.dcsoft.com> wrote in message
news:8438CB1A-C21F-4A9E-9950-D3E4822D9D8D(a)microsoft.com...
> It is a good general rule to keep all UI on the main thread. But it is
> safe to create and access additional windows on a separate thread. This
> is especially true in this case where the MATLAB window is disabled while
> yours is active, so there is no chance the user can simultanously mix the
> two. The rule is the window must be accessed only from the thread it is
> created in. In the new thread, make sure you init OpenGL and OLE if
> necessary.
>

Oops, I guess your window and MATLAB will be active simultaneously, which is
the whole point of this! ;) So you will have both MATLAB's and your
thread's message pumps dispatching messages simultaneously. This should be
OK. In your exported function, if it finds the thread and window already
created, I would post messages to your window to pass the new graphing
parameters, rather than access it the window directly. Also, you may need
to add code in DllMain() so when the process detaches, you close the window
and exit the thread, since MATLAB won't know to clean up these. If you do
nothing, Windows will of course destroy your window and unload your DLL
anyway, but I don't know how cleanly.

-- David


From: Hector Santos on
In principle, each thread that wishes to have its own GUI needs a
message queue processor to pump messages to the controls.

Every EXE has a main thread and every GUI EXE has a message queue
associated with the main thread to draw things.

So if you have secondary threads to do background processing, in my
design experience there were two safe ways to pass "data" that is
going to be drawn in the main thread GUI window:

1) Using SendMessage/PostMessage:

The secondary thread calls SendMessage() (send/wait) or PostMessage()
(send/no wait) to the Main thread Message Queue. Here you have to
create some "buffer" to pass via the Send/PostMessage().

If you call SendMessage() which is a SEND/WAIT for completion, you can
pass a pointer to the local buffer and use it in the main thread
because it will still be "alive" when the main thread gets it.

If you call PostMessage() which is a SEND/NO WAIT, then here you are
queuing the message in main thread message queue to be processed when
the main thread message pump gets to it at some delayed time. So
here, you need to pass a new allocated buffer pointer that the
eventual main thread processing will release.

2) Using a common shared Data Structure.

Here you prepare a common (GLOBAL) data structure filled with fields
and information that:

1) The secondary thread fills (WRITE)

2) The main thread via a TIMER or a "WAKE UP" event will
READ data structure to update "refresh" the screen.

Here you need to synchronize using locks (semaphores, mutexes, etc)
the WRITE/READ of the shared common resource (data structure) to
prevent potential clobbering of data.

For example, lets say you want to data points in the main form window.

Counter1: ________ << member controls m_Counter1
Counter2: ________ << member controls m_Counter2

That is updated per threads:

typedef struct _tagCommonData {
int data1;
int data2;
} COMMONDATA;

The easiest lock and guaranteed to be CORRECT and SAFE is a Critical
Section but it also the least efficient (speed wise) because its a
mutual exclusive READ or WRITE only operation, never two threads can
access it at the same time which is possible with a concept called
ReaderWriter Locks. ReaderWriter are easy if you get the proper class
from some library.

So you create a global data and critical section:

COMMONDATA globalData = {0};
CCriticalSection csLock();

Now in your secondary threads, your lock and write to the structure:

MyThread1()
{
csLock.Lock(0);
globalData.data1++;
csLock.Unlock();
}

MyThread2()
{
csLock.Lock(0);
globalData.data2++;
csLock.Unlock();
}

Now in your main program, you add a OnTimer() lets say for evert 100
milliseconds.

MyMainWindow::onTimer()
{
csLock.Lock(0);
m_Counter1 = data1;
m_Counter2 = data2;
csLock.Unlock();
}

You can add some efficiency ideas by only updating if dirty:

MyMainWindow::onTimer()
{
csLock.Lock(0);
if (m_Counter1 != globalData.data1)
m_Counter1 = globalData.data1;

if (m_Counter2 != globalData.data2)
m_Counter2 = globalData.data2;
csLock.Unlock();
}

Instead of a timer, you can consider using a signal like a custom
registered WM_MY_REFRESH message that will call a OnMyRefresh()
message handler in your MyMainWindow to do the screen updating. This
makes it more dynamic if there aren't tons of updating going on.

A Reader/Writer lock allows you to add logic like a Writer Thread puts
a lock on ALL allowing only One writer at a time, but you can have
Multiple Readers as long as they are no active writers. So this an
more efficient than a Critical Section.

So the child threads will enable a Writer Lock:

MyThread2()
{
csReaderWriter.Write();
globalData.data2++;
csReaderWriter.Unlock();
}

and the main thread will use a Reader Lock:

MyMainWindow::onTimer()
{
csReaderWriter.Reader();
if (m_Counter1 != globalData.data1)
m_Counter1 = globalData.data1;

if (m_Counter2 != globalData.data2)
m_Counter2 = globalData.data2;
csReaderWriter.Unlock();
}

The above reader/writer lock example is pseudo code, I don't see a MFC
based Reader/Writer class but there are many in the public domain.

Finally, if you want the child threads to have their own GUI, then the
same and only requirement is that the thread has own message pump.
The same "Inter Thread" communications apply here as with dealing with
the main thread only.

--
HLS


JRGlide wrote:

> Thank you. You are right that MATLAB loads a DLL and then calls another DLL
> which displays the data. In case it matters, the viewing program is an
> application that I converted into a DLL, so it has its own CWinApp, menus,
> CView, etc. In fact, you may have been the one who helped me develop it
> several years ago.
>
> My question about your approach is that I alway read on this forum that the
> GUI should always be in the application and never in a thread - that only
> processing should be done is a separate thread. So why is this different?
>
>
> "David Ching" wrote:
>
>> It sounds like MATLAB loads your DLL and calls an exported function which
>> shows the 3D window. And when user closes the window, only then does the
>> exported function return to MABLAB. So MATLAB waits for your exported
>> function to return before allowing any more interaction with the main MATALB
>> window.
>>
>> If so, why don't you alter your exported function to create a new thread
>> that shows the 3D window and returns immediately? Then MATLAB and the 3D
>> window function simultaneously. The next time MATLAB calls your exported
>> function, you check if the thread/3D window already appear and pass the new
>> graph data to the window, if so.
>>
>> -- David
>>
>>
>> "JRGlide" <JRGlide(a)discussions.microsoft.com> wrote in message
>> news:75C5F17D-92D6-465A-97DE-50B741907E58(a)microsoft.com...
>>> I currently have a MATLAB mex function that allows the user to view &
>>> manipulate 3D point cloud data directly from MATLAB. A mex function is
>>> nothing more than a standard dll with a specific MATLAB entry point. The
>>> viewer was written in MFC using OpenGL.
>>>
>>> My problem is that since it is a dll the user must close the viewer before
>>> returning to MATLAB. In other words, the user calls the viewer from
>>> MATLAB,
>>> looks at the data, closes the viewer and then returns to MATLAB.
>>>
>>> I would like to find a way to keep the viewer up permanently so that it
>>> works independently from MATLAB so they can both be run at once. What I
>>> envision is that MATLAB would call another mex function (or dll) with the
>>> data for display. This function would check to see if the viewer is
>>> active
>>> and activate it if necessary. It would then pass the data to the viewer
>>> using some sort of handshake and then return to MATLAB without the viewer
>>> disappearing at it does now. If the user changed the data it would make
>>> the
>>> same call and the dll would update the data in the viewer.
>>>
>>> My question is that I'm not sure how to go about doing this:
>>>
>>> 1. I suspect that to do this, the viewer would need to be a regular
>>> executable with some sort of interface and not a dll, but maybe I assume
>>> wrong.
>>>
>>> 2. It would first have to know if the viewer is loaded or not and the
>>> load
>>> it.
>>>
>>> 3. I'm not sure what the handshake would be between the mex function and
>>> the viewer. The data could potentially be hundreds of megs in size. Is
>>> there a way I can do that through shared memory or some sort of global
>>> memory
>>> pool? I'm trying to keep from writing the data to disk and read it back
>>> again. Having said that, if I have to limit the data size to say, less
>>> than
>>> 50 meg, I can live with that.
>>>
>>> 4. As far as closing the viewer, I guess that would be up to the user
>>> after
>>> they are finished, just like any other application.
>>>
>>> Thank you for your help.
>>>
>>
>>

From: JRGlide on
Thank you everyone for your answers. I have lots to think about now, but at
least I know it can be done, which is the first hurdle.

As for Joe's question about unloading the DLL, it is partly a MATLAB issue
and partly my design flaw. Here is the data flow:


*************** ************** *************
* * * * *
*
* MATLAB * --> * mex function * --> * 3D Viewer *
* * * * *
*
*************** ************** *************

Since the mex function is a DLL, MATLAB will not return until the mex
function returns. But I also implemented the viewer as another DLL, so the
mex function does not return until the viewer also returns. But if I convert
the viewer to an exe and implement the handshake people have suggested, then
I hope that it will stay resident.

As far as ActiveX as Joe suggested, that was going to be a future question!
I read about it once and it didn't sound easy. MATLAB supports ActiveX
controls, which might be nice within a MATLAB GUI.

As for the data format, the data is simple (x,y,z) floating point data so
the data passing is simple. However, I missed my memory estimates by about a
factor of 10! I can't see anyone wanting to pass in more than a million
points, which is 36 MB of data, so it shouldn't be in the 100's like I said.
Then again, no matter what capabilities this has, the engineers always want
more!
From: JRGlide on

I was afraid that the formatting might not come out right. I guess I'll
never try that again...