Connection Points.

Connction Point Source

Connection points provide events for comet, and rely on tlb2h (see Tlb2h Usage) to generate the implementation for each method on the interface.

Then comet::implement_cpc is used to provide IConnectionPointContainer (which provides the method for finding a particular connection point.

The default implementation of a coclass will inherit of this method by default, however they can be explicitly referenced to provide alternate implementations.

The class comet::implement_cpc is templated to an interface list, which can be constructed with comet::make_list.

    class my_class : public simple_object< IFooImpl<my_class>, implement_cpc< make_list<IFooEvent, IBarEvent>::result > >

This causes each of the interface in the list of interfaces to be wrapped by a comet::connection_point_for class which provides the access syntax.

    connection_point_for<IFooEvent>::connection_point.Fire_FooMethod( args );

Note that Fire_ is prepended to each method name.

If there is only one connection point in the list, then the connection_point_for namespace segregator is not required.

If there is no connection point implementation for the interface, then you should make sure that it is referenced with a [source] tag by a coclass definition in the library you are including, and that you are generating server implementations or forcing it by prepending '*' in a symbol file, see the Symbol File Format.

Connction Point Sink

In order to prevent the circular references inherent in connection points, the reference loop must be broken somehow. This is best done by using a contained member that calls back on the parent class.

The class sink_impl is best used in this circumstance as it contains code for calling Advise and Unadvise. It inherits from static_object which is designed to be embedded in a class, and does reference counting on the module and does not destruct itself.

This class is templated to the interface implementation desired, which will mostly be the 'Impl' class for the interface, but might be a raw COM interface.

In this example we have a class 'MyCoclass' that is sinking the event interface IMyEventImpl which has a single 'EventHappened' method.

        class coclass_MyCoclass : public coclass<MyCoclass>
        {
                // Private Embedded sink implementation.
                struct sink_t  : sink_impl<IMyEventImpl>
                {
                        sink_t(coclass_MyCoclass *Parent) :m_parent(Parent) {}
                        inline void EventHappened( long param_Here ) { m_parent->sink_EventHappened(param_Here); }
                        coclass_MyCoclass *m_parent; // Non-addref reference.
                } m_sink;
                public:
                        coclass_MyCoclass() : m_sink(this) {}

                        // Set the event source.
                        void SetEventSource( const com_ptr<IUnknown> &unknown)
                        {
                                if (m_sink.is_advised())
                                        m_sink.unadvise();
                                m_sink.advise( unknown );
                        }

                        inline void sink_EventHappened( long param_Here )
                        {
                                // Event code goes here
                        }
        };