Page 1 of 1

COFE collapses when using CoUninitialize in destruction

Posted: 10 August 2014, 08:29
by bcbooo
I have finished a simple Unit Operation, it performs very good in the environment of Aspen Plus, but easily collapses in the environment of COFE.

The following is episode of my code:

Code: Select all

// some construction code
SampleUnitOperation :: SampleUnitOperation
{
CoInitialize(NULL);
// have defined CComPtr<IThermoCompound> tc;
HRESULT hr=tc.CoCreateInstance(clsid);
}

Code: Select all

//some destruction code
SampleUnitOperation :: ~SampleUnitOperation
{
tc=NULL;
CoUninitialize();
}
Well, there's no error with the code, but after the process finished in the COFE, COFE will collapse at this case:

click "Solve", then click "Reset", then click "Solve", then click "Reset", then again "Solve". At this moment, COFE will appear this window:(at the attachment)

Then I tested the COFE, I find when click "Solve", the COFE will call the construction function "SampleUnitOperation :: SampleUnitOperation" twice. But Aspen Plus only calls this construction function at the first time when inserts this Unit Operation, not at the "Solve" function.

So the collapsion of COFE is the conflict of construction function and destruction function, COFE's twice calling on "Solve" results in the chaos of COM reference.

So, why does COFE call Unit Operation's construction function at the "Slove" command twice? It's rational to call construction at the Unit Operation's creation, not the "Solve".

And where should I release the "tc" COM pointer and call "CoUninitialize"?

Thank you Jasper, any response will be appreciated.

Re: COFE collapses when using CoUninitialize in destruction

Posted: 10 August 2014, 09:26
by jasper
There are two things of your mail rather unclear to me:

1) why would a PMC call CoInitialize and CoUninitialize? I presume your unit operation is a CAPE-OPEN COM object, so the COM initialization is already done by the PME that created your unit operation. What is your point of re-initializing COM?

2) why would a unit operation create an object that implements ICapeThermoCompounds?

Re: COFE collapses when using CoUninitialize in destruction

Posted: 10 August 2014, 09:29
by jasper
To answer your question about the second CoCreateInstance: by default COFE does not solve in the main thread. It solves in a background thread. As COFE uses the apartment threaded model, it cannot use the unit operations from the main thread in the solution thread. Therefore, it saves the one in the main thread, creates a new one in the solution thread, and restores it from the saved one. Now there are two copies; one in the main thread and one in the solution thread.

You can turn this off (in preferences you can untick the box to use a separate thread for solutions) but now solving is done in the main thread, which makes the application respond less. More-over, this is the calling pattern to be expected in any multi-threaded CAPE-OPEN application. See here for more info:

http://cocosimulator.org/down.php?dl=AI ... _notes.pdf

Re: COFE collapses when using CoUninitialize in destruction

Posted: 11 August 2014, 02:23
by bcbooo
Sorry Jasper, it's my fault to re-initialize COM. And I don't implement ICapeThermoCompounds at there, it's just a sample.

But there are still errors. My code is modified as the following:

Code: Select all

SampleUnitOperation :: SampleUnitOperation
{
// have defined CComPtr<ISample> tc;
HRESULT hr=tc.CoCreateInstance(clsid);
}

SampleUnitOperation :: ~SampleUnitOperation
{
tc=NULL;
}
If I called "tc=NULL" in the destruction, the collapsion still occurs. I don't know why.

Re: COFE collapses when using CoUninitialize in destruction

Posted: 11 August 2014, 07:14
by jasper
Is tc a shared resource (e.g. a global variable, or a static variable)? How is it declared?

If there is only one copy of tc I would expect things to go wrong indeed.

Re: COFE collapses when using CoUninitialize in destruction

Posted: 11 August 2014, 07:37
by bcbooo
Yeah, tc is a global variable.

tc is defined in a individual file:

Code: Select all

//header file, PublicVariable.h
extern CComPtr<ISample> tc;

Code: Select all

//cpp file, PublicVariable.cpp
CComPtr<ISample> tc=NULL;

Re: COFE collapses when using CoUninitialize in destruction

Posted: 11 August 2014, 07:53
by jasper
Why do you not make it a class variable?

Re: COFE collapses when using CoUninitialize in destruction

Posted: 11 August 2014, 07:55
by jasper
Alternatively, is this is an object to be shared by multiple unit operations, keep a reference count on it. Delete it when the last unit operation is deleted.

But this will surely give you thread safety problems. Suppose you have two threads that each have a unit operation, and that are calculating at the same time; they will be accessing the tc object simultaneously. You would need to synchronize access to this object.

Re: COFE collapses when using CoUninitialize in destruction

Posted: 11 August 2014, 08:05
by bcbooo
tc is not shared by multiple Unit Operations, but shared by many functions in different classes. In my application tc is used to get some public data.

Now my strategy is not to call "tc=NULL" in destruction.

Re: COFE collapses when using CoUninitialize in destruction

Posted: 11 August 2014, 08:29
by jasper
This will not resolve your conflict regarding tc being used by two different unit operations. I suggest you make tc a member variable of the unit operation class.