Click here to Skip to main content
15,904,416 members
Please Sign up or sign in to vote.
4.00/5 (2 votes)
See more:
Hello,

In c++, MFC:

I have a CComPointer:

CComPointer<IMyTask>				m_pTask;	


there are a lot of places in my code, I call to this ComPointer to run the task's methods. For example:

C++
void method1()
 {
    if (FAILED(hRet = m_pTask->MyFunc1()))
                  .....
 }

void method2()
{
    if (FAILED(hRet = m_pTask->MyFunc2()))
                  .....
}



I try to solve a problem to recover when MyTask is down.
I wrote a method, recover(), that rerun the CoCreate to MyTask, and it actually solves the problem.

I could see that if MyTask is dead, i get an HR fail code of -2147023174, RPC server is unavailable. But, the com pointer m_pTask has the full data (it doesn't know the task is dead).

I can do something like this:

C++
void method1()
 {
    if (FAILED(hRet = m_pTask->MyFunc1()))
        if (hRet == -2147023174)
           recover();
                  .....
 }

void method2()
{
    if (FAILED(hRet = m_pTask->MyFunc2()))
        if (hRet == -2147023174)
           recover();
                  .....
}



But, because I have alot of calling to methods via the compointer, I want to make something more general.
I want that everytime I try to run a method via the ComPointer, before the runnuing of the method, to check that the task is already exists, and if not - run the recover method.
Since even when the task is dead, ComPointer still has all the data from the CoCreate time, I don't know how can I do it.

How can I do it?

The task is dead due to an error that occurs sometiems in the system, and for now my solution does not need to find the reason for the task failure, just to recover it. I am looking for a general solution - like a wrapper to the ComPointer, but I want that the wrapper class will only check if MyTask is still exists, and if it is -it will return the ComPointer, and if not, it will run recover.

How can I do it?

Thanks
Posted
Updated 6-Jun-12 3:06am
v2

At first a would use the define-value of -2147023174 to enhance code quality.

Use a bool for the last known running state. That fires up perfomance because it doesnt need to call some COM-overhead.
 
Share this answer
 
Comments
user_code 6-Jun-12 8:09am    
Thanks for your answer.
Can you please explain with more details? I'm not sure I understood it exactly..
Thanks
You need something to catch errors transparently and do some recovery action, it sounds like a job for a proxy object.

Bascially your current interface doesn't quite cut it as far as transparency of recovery goes. The idea here is that you implement you interface again in a containing (proxy) object that passes calls through to the real object handling any errors that come out, all without the caller knowing.

Say you have an interface A, it's got one member, f:
C++
class A
{
    public:
        virtual bool f() = 0;
};
The idea is that f does something useful, returning false if something breaks. This is the equivalent of your COM interface.

You've implemented this interface in B...
C++
class B : public A
{
    public:
        virtual bool f();
};
This is the equivalent of your CoClass. The problem is that f's returning false a bit too often and your code is full of chaff like:
C++
void do_something( A *ptr )
{
    if( !ptr && !ptr->f() )
    {
        do_remedial_action();
    }
}
It's okay with one function, but wait until you implement some more on your interface!

So how can you hide the whole problem?

1. Declare a new class, a proxy, which implements A:
C++
class recoverable_proxy_for_A : public A
{
    public:
        virtual bool f()
        {
            return false;
        }
};
Doesn't do a lot does it? Hang in there!

2. Add a constructor for recoverable_proxy_for_A which takes an instance of an object implementing A:
C++
class recoverable_proxy_for_A : public A
{
    public:
        recoverable_proxy_for_A ( A *to_be_proxied )
            : proxied_( to_be_proxied )

        virtual bool f()
        {
            return false;
        }

    private:
        A *proxied_;
};
3. Implement recoverable_proxy_for_A by calling through to the contained A:
C++
class recoverable_proxy_for_A : public A
{
    public:
        recoverable_proxy_for_A ( A *to_be_proxied )
            : proxied_( to_be_proxied )

        virtual bool f()
        {
            return proxied_->f();
        }

    private:
        A *proxied_;
};
4. Finally add the magic thing bit in... Handle the error in the call to recoverable_proxy_for_A::f:
C++
class recoverable_proxy_for_A : public A
{
    public:
        recoverable_proxy_for_A ( A *to_be_proxied )
            : proxied_( to_be_proxied )

        virtual bool f()
        {
            if( !proxied_->f() )
            {
                do_remedial_action();
                return proxied_->f(); // try again perhaps?
            }

            return true;
        }

    private:
        A *proxied_;
};
The you can replace every use of instance of something implementing A in your code with recoverable_proxy_for_A and your error checking happens automagically.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900