Monday, December 27, 2010

Basic pattern for Events in C++/CLI

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

public ref class CManaged 
{
public:
    delegate bool CallbackHandler(int);
    // For user to register handler
    event CallbackHandler^ OnCallback
    {
        void add(CallbackHandler^ handler)
        {
            lock lockEvents(this);
            m_callback = (CallbackHandler^) m_callback->Combine(m_callback, handler);
        }
        void remove(CallbackHandler^ handler)
        {
            lock lockEvents(this);
            m_callback = (CallbackHandler^) m_callback->Remove(m_callback, handler);
           
        }
    protected:
        bool raise(int n)
        {
            bool ret = true;
            for each(CallbackHandler^ handler in m_callback->GetInvocationList()){
                ret = ret && handler->Invoke(n);
            }
            return ret;
        }
    }

private:
    CallbackHandler^ m_callback;

public:
    CManaged()
    {
    }
    ~CManaged()
    {
    }

    bool InvokeCallback(int n)
    {
        if(m_callback)
            return m_callback->Invoke(n);
        return false;
    }

    bool Callback(int n)
    {
        printf("%d\n", n);
        return true;
    }
};

int main(array ^args)
{
    CManaged^ c = gcnew CManaged;
    c->OnCallback +=  gcnew CManaged::CallbackHandler(c, &CManaged::Callback);
    c->OnCallback +=  gcnew CManaged::CallbackHandler(c, &CManaged::Callback);

    c->InvokeCallback(1);
    c->InvokeCallback(2);
    return 0;
}

Wrapping C/C++ callback in C++/CLI


/**
 * Unmanaged part
 */

typedef boost::function UnmanagedCallback;
typedef bool (__stdcall *CallbackTypeProxy)(int);

class CUnmanaged {
private:
    boost::function m_callback;
public:
    CUnmanaged(const boost::function & callback) : m_callback(callback)
    {
    }

    bool Callback(int n)
    {
        return m_callback(n);
    }
};

/**
 * Managed part
 */

using namespace System::Runtime::InteropServices;

public ref class CManaged 
{
private:
    delegate bool CallbackHandler(int);
    CallbackHandler^ m_callback;
    CUnmanaged * m_object;

    bool Callback(int n)
    {
        printf("%d\n", n);
        return true;
    }
public:
    CManaged()
    {
        m_callback = gcnew CallbackHandler(this, &CManaged::Callback);
        System::IntPtr ip = Marshal::GetFunctionPointerForDelegate(m_callback);
        CallbackTypeProxy cb = static_cast(ip.ToPointer());

        m_object = new CUnmanaged(boost::bind(cb, _1));
    }
    ~CManaged()
    {
         delete m_object;
    }

    bool InvokeCallback(int n)
    {
        return m_object->Callback(n);
    }
};

int main(array ^args)
{
    CManaged c;
    c.InvokeCallback(1);
    c.InvokeCallback(2);
    return 0;
}


Friday, December 10, 2010

Windows Session, Desktop, and Station

http://blogs.technet.com/b/markrussinovich/archive/2010/02/24/3315174.aspx



http://blogs.technet.com/b/askperf/archive/2007/07/24/sessions-desktops-and-windows-stations.aspx

A session consists of all of the processes and other system objects that represent a single user’s logon session. 
These objects include all windows, desktops and windows stations.
A windows station is basically a security boundary to contain desktops and processes.


So, a session may contain more than one Windows Station and each windows station can have multiple desktops.


http://www.brianbondy.com/blog/id/100/

http://blogs.msdn.com/b/winsdk/archive/2009/07/14/launching-an-interactive-process-from-windows-service-in-windows-vista-and-later.aspx

Use sysinternals psexec to spawn process in another session, e.g.
% psexec -s -i 3 E:\__tmp\CUDA\Benchmark\Release\benchmark -r

How psexec works