I have uploaded to my blog
(http://traxnet.wordpress.com/2009/12/24/synchronizationcotext-for-cocoamono
bjc/) the code of our implementation of a SynchronizationContext for
Cocoa/Monobjc. Please feel free to comment the implementation, correct it or
improve it too.

 

 If you feel like it is ok, we don't mind if you publish the article  or the
code directly on the Monobjc page or in whatever place you think could be
useful for others. 

 

Happy Christmas all,

 

Oscar Blasco                        
Senior Software Developer
Video Stream Networks, S.L. 
Telf. +34 96 5993670
Fax. +34 96 5993673
obla...@vsn.es
www.vsn-tv.com <http://www.vsn-tv.com/> 

 

 

------------------------------------------------

 

using System;

using System.Collections.Generic;

using System.Text;

using System.Threading;

using Monobjc.Cocoa;

using Monobjc;

 

namespace vsn.MacOSXComponents.Threading

{

    [ObjectiveCClass]

    public class SyncObject : NSObject

    {

        private SendOrPostCallback m_Callback;

        private Object m_State;

 

        public delegate void DeregisterDelegate(SyncObject sync_object);

#if USE_SYNCOBJS_DICTIONARY

        private DeregisterDelegate m_DeregisterDelegate;

#endif

 

         public static readonly Class SyncObjectClass =
Class.GetClassFromType(typeof(SyncObject));

 

        ///

        /// Initializes a new instance of the  class.

        ///

        public SyncObject() { }

 

        ///

        /// Initializes a new instance of the  class.

        ///

        ///

 

        public SyncObject(IntPtr nativePointer)

            : base(nativePointer) { }

 

        public override void  Dispose()

         {

                 // This is here for testing purpouses

                 //Console.Write("Disposing SyncObject");

                 base.Dispose();

         }

 

        ///

        /// initializes the synchronization object with the given call back
and object state

        ///

        /// callback

        /// state

        /// if true, the current thread waits until the operation is
performed

        ///

 

        public void Initialize(SendOrPostCallback d, Object state, bool
wait, DeregisterDelegate dereg_delegate)

        {

            m_Callback = d;

            m_State = state;

#if USE_SYNCOBJS_DICTIONARY

            m_DeregisterDelegate = dereg_delegate;

#endif

 

            // Call the NSObject's performSelector method from csharp code

 
PerformSelectorOnMainThreadWithObjectWaitUntilDone(ObjectiveCRuntime.Selecto
r("bridgedCallback:"), this, wait);

        }

 

        ///

        /// This is our callback which is invoked by the main thread's
runloop

        ///

        [ObjectiveCMessage("bridgedCallback:")]

        public void BridgedCallback(NSObject param)

        {

            // Invoke the true callback

            m_Callback(m_State);         

 

#if USE_SYNCOBJS_DICTIONARY

             // Un register this object from our cache

            if (m_DeregisterDelegate != null)

                m_DeregisterDelegate(this);

#endif

 

                 // This region is unsafe as we are not protected against
the GC. Monobjc

                 // has a cached reference to this object so shouldn't be a
problem but

                 // could be a problem if the implementation changes.

                 // Consider using a CER

                 // GC.Collect(); // Testing

 

                 // Mark this object for deletion by an AutoreleasePool

                 this.Autorelease();

        }

    }

 

    ///

    /// Cocoa's SynchronizationContext implementation

    ///

    /// Only Post and Send methods are implemented

    ///

    public class CocoaRunLoopSynchronizationContext : SynchronizationContext

    {

        private Dictionary m_SyncObjectsDictionary;

        private readonly object m_lock = null;

 

        ///

        /// Default constructor

        ///

        public CocoaRunLoopSynchronizationContext()

            : base()

        {

            m_SyncObjectsDictionary = new Dictionary();

            m_lock = new object();

        }

 

        public override void Post(SendOrPostCallback d, Object state)

        {

             SyncObject sync = new SyncObject();

#if USE_SYNCOBJS_DICTIONARY

            lock(m_lock)

               m_SyncObjectsDictionary.Add(sync.GetHashCode(), sync);

#endif

            sync.Initialize(d, state, false, DeregisterSyncObject);

 

        }

 

        public override void Send(SendOrPostCallback d, Object state)

        {

            SyncObject sync = new SyncObject();

#if USE_SYNCOBJS_DICTIONARY

            lock (m_lock)

                m_SyncObjectsDictionary.Add(sync.GetHashCode(), sync);

#endif

            sync.Initialize(d, state, true, DeregisterSyncObject);

        }

 

        ///

        /// Called by SyncObject to remove itself from the dictionary so
that no reference is held

        ///

        ///

target object to unregister

        private void DeregisterSyncObject(SyncObject sync_object)

        {

#if USE_SYNCOBJS_DICTIONARY

             lock (m_lock)

                 m_SyncObjectsDictionary.Remove(sync_object.GetHashCode());

#endif

        }

    }

}

 

 

 

Reply via email to