Click here to Skip to main content
15,886,137 members
Articles / General Programming / Threads

Declarative multithreading

Rate me:
Please Sign up or sign in to vote.
4.94/5 (39 votes)
13 Mar 2012CDDL19 min read 57.9K   862   139  
An introduction and proof of concept code for the idea of declarative multi threading in C#.
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Threading;

namespace ThreadBound
{
    /// <summary>
    /// Describes the various call states of a remote method.
    /// <list type="bullet">
    /// <item>
    ///     <term>Waiting</term>
    ///     <description>The message is waiting to be executed.</description>
    /// </item>
    /// <item>
    ///     <term>Running</term>
    ///     <description>The message is currently executing.</description>
    /// </item>
    /// <item>
    ///     <term>Done</term>
    ///     <description>The message was executed.</description>
    /// </item>
    /// <item>
    ///     <term>Cancel</term>
    ///     <description>The execution of this message was canceled.</description>
    /// </item>
    /// </list>
    /// </summary>
    public enum CallStates { Waiting = 0, Running = 1, Done = 2, Canceled = 10 };

    /// <summary>
    /// This interface must be implemented by every class representing a method call within the
    /// queue of the SynchronisationContext. This interface triggers the execution of the method
    /// call on the remote side.
    /// </summary>
    internal interface IRemoteMethod
    {
        /// <summary>
        /// Returns the IMethodCallMessage interface describing the method call represented by this IRemoteMethod instance.
        /// </summary>
        IMethodCallMessage CallMessage { get; }

        /// <summary>
        /// Sets the return message of the method call.
        /// </summary>
        /// <param name="returnMessage"></param>
        void SetReturnMessage(IMethodReturnMessage returnMessage);

        /// <summary>
        /// Sets the state of the method call. This enables the retrieval of the execution state of asynchronous method calls via the IAsyncCallState interface.
        /// </summary>
        /// <param name="newState">The new call state to set.</param>
        /// <seealso cref="SyncRemoteMethod.SetState(CallStates newState)"/>
        /// <seealso cref="AsyncRemoteMethod.SetState(CallStates newState)"/>
        /// <returns>Returns true if the state transition was valid.</returns>
        bool SetState(CallStates newState);

        /// <summary>
        /// Checks if the method call represented by the instace of the object implementing this interface was canceled.
        /// </summary>
        /// <returns>Returns true if the method call was canceld or false otherwise.</returns>
        bool WasCanceled();
    }

    /// <summary>
    /// Transports all parameters for a synchronous method call to the remote side.
    /// </summary>
    internal class SyncRemoteMethod :
        IRemoteMethod
    {
        private IMethodCallMessage InternalCallMessage;
        private IMethodReturnMessage InternalReturnMessage;

        /// <summary>
        /// c'tor: Constructing a SyncRemoteMethod from an IMethodCallMessage interface.
        /// </summary>
        /// <param name="callMessage">IMethodCallMessage interface describing the method to call on the remote side.</param>
        public SyncRemoteMethod(IMethodCallMessage callMessage)
        {
            InternalCallMessage = callMessage;
        }

        /// <summary>
        /// Returns the IMethodCallMessage interface describing the method call represented by this IRemoteMethod instance.
        /// </summary>
        /// <seealso cref="IRemoteMethod.CallMessage"/>
        public IMethodCallMessage CallMessage
        {
            get { return InternalCallMessage; }
        }

        /// <summary>
        /// The return Message of the method call.
        /// </summary>
        /// <seealso cref="SyncRemoteMethod.SetReturnMessage(IMethodReturnMessage returnMessage)"/>
        public IMethodReturnMessage ReturnMessage
        {
            get { return InternalReturnMessage; }
        }

        /// <summary>
        /// Saves the return message of the synchronous method call. The Return message can be retrieved by the ReturnMessage method of this class.
        /// </summary>
        /// <seealso cref="IRemoteMethod.SetReturnMessage(IMethodReturnMessage returnMessage)"/>
        /// <seealso cref="SyncRemoteMethod.ReturnMessage"/>
        /// <param name="returnMessage">The IMethodReturnMessage interface containing the result of the method call.</param>
        public void SetReturnMessage(IMethodReturnMessage returnMessage)
        {
            InternalReturnMessage = returnMessage;
        }

        /// <summary>
        /// Sets the new state of this method call.
        /// </summary>
        /// <seealso cref="IRemoteMethod.SetState(CallStates newState)"/>
        /// <param name="newState">The new call state to set.</param>
        /// <returns>Returns always true because setting the state on a synchronous method call is not supported.</returns>
        public bool SetState(CallStates newState)
        {
            return true;
        }

        /// <summary>
        /// Checks if the remote method was cancled.
        /// </summary>
        /// <seealso cref="IRemoteMethod.WasCanceled()"/>
        /// <returns>Always returns false because a synchronous method call can not be canceled.</returns>
        public bool WasCanceled()
        {
            return false;
        }
    }

    /// <summary>
    /// Transports all parameters for an asynchronous method call to the remote side.
    /// </summary>
    internal class AsyncRemoteMethod :
        IRemoteMethod,
        IAsyncCallState
    {
        /// <summary>
        /// Saves the current call state of the method call represented by this AsyncRemoteMethod instance
        /// </summary>
        private CallStates CurrentCallState;

        /// <summary>
        /// Object used for locking the CurrentCallState variable for threadsafe access.
        /// </summary>
        private object CallStateLock = new object();

        /// <summary>
        /// The IMethodCallMessage interface of the stored method call. This interface is implemented by the used MethodCallMessageWrapper instance.
        /// </summary>
        private IMethodCallMessage StoredCallMessage;

        /// <summary>
        /// c'tor: Constructs an AsyncRemoteMethod instance from a IMethodCallMessage interface. The contents of the IMethodCallInterface will be wrapped by a
        /// MethodCallMessageWrapper instance.
        /// </summary>
        /// <param name="callMessage">IMethodCallMessage interface describing the method to call on the other thread.</param>
        public AsyncRemoteMethod(IMethodCallMessage callMessage)
        {
            CurrentCallState = CallStates.Waiting;

            //-- Using MethodCallMessageWrapper to wrap all Parameters up and ensure they are not freed until the call
            //   on the remote sinde has completed. This is a little unofficial - but better than doing it manually.
            StoredCallMessage = new MethodCallMessageWrapper(callMessage);
        }

        /// <summary>
        /// Returns the IMethodCallMessage interface describing the method call represented by this IRemoteMethod instance.
        /// </summary>
        /// <seealso cref="IRemoteMethod.CallMessage"/>
        public IMethodCallMessage CallMessage
        {
            get
            {
                return StoredCallMessage;
            }
        }

        /// <summary>
        /// Sets the return message of the asynchronous method call. The parameter will simply be ignored because asynchronous calls can't return values.
        /// </summary>
        /// <seealso cref="IRemoteMethod.SetReturnMessage(IMethodReturnMessage returnMessage)"/>
        /// <seealso cref="SyncRemoteMethod.ReturnMessage"/>
        /// <param name="returnMessage">The IMethodReturnMessage interface containing the result of the method call.</param>
        public void SetReturnMessage(IMethodReturnMessage returnMessage)
        {
        }

        /// <summary>
        /// Sets the state of the method call. This enables the retrieval of the execution state of asynchronous method calls via the IAsyncCallState interface.
        /// </summary>
        /// <param name="newState">The new call state to set.</param>
        /// <seealso cref="IRemoteMethod.SetState(CallStates newState)"/>
        /// <returns>Returns true if the state transition was valid. A state transition is only valid of the current state is less than the new state. See CallStates enumeration for details.</returns>
        public bool SetState(CallStates newState)
        {
            bool bValidTransition = true;

            lock (CallStateLock)
            {
                if (CurrentCallState < newState)
                    CurrentCallState = newState;
                else
                    bValidTransition = false;
            }

            return bValidTransition;
        }

        /// <summary>
        /// Returns the current state of the call.
        /// <list type="bullet">
        /// <item>
        ///     <term>Waiting</term>
        ///     <description>The asynchronous call is waiting to be executed.</description>
        /// </item>
        /// <item>
        ///     <term>Running</term>
        ///     <description>The asynchronous call is currently executed.</description>
        /// </item>
        /// <item>
        ///     <term>Done</term>
        ///     <description>The asynchronous call was executed.</description>
        /// </item>
        /// <item>
        ///     <term>Cancel</term>
        ///     <description>The execution of this call was canceled.</description>
        /// </item>
        /// </list>
        /// </summary>
        public CallStates CallState
        {
            get
            {
                CallStates callState;
                lock (CallStateLock)
                    callState = CurrentCallState;
                return callState;
            }
        }

        /// <summary>
        /// Checks if the remote method was cancled.
        /// </summary>
        /// <seealso cref="IRemoteMethod.WasCanceled()"/>
        /// <returns>Returns true if the execution of this method call was canceled by a call to <see cref="IAsyncCallState.Cancel()">IAsyncCallState.Cancel().</see></returns>
        public bool WasCanceled()
        {
            return (CallState == CallStates.Canceled);
        }

        /// <summary>
        /// Cancels the execution of this method. If the method is already executing, the thread will be notified about
        /// the cancelation. If not, the call state will be set to canceled so the method will never be executed.
        /// </summary>
        public void Cancel()
        {
            SetState(CallStates.Canceled);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
Systems Engineer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions