WidcommPortSingleThreader.cs :  » Business-Application » 32feet.NET » InTheHand » Net » Bluetooth » Widcomm » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Business Application » 32feet.NET 
32feet.NET » InTheHand » Net » Bluetooth » Widcomm » WidcommPortSingleThreader.cs
// 32feet.NET - Personal Area Networking for .NET
//
// InTheHand.Net.Widcomm.WidcommSocketExceptions
// 
// Copyright (c) 2008-2009 In The Hand Ltd, All rights reserved.
// Copyright (c) 2008-2009 Alan J. McFarlane, All rights reserved.
// This source code is licensed under the In The Hand Community License - see License.txt

#if WIDCOMM_SINGLE_THREADING
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;

namespace InTheHand.Net.Bluetooth.Widcomm{
    class WidcommPortSingleThreader : IDisposable
    {
        Queue<StCommand> m_actions = new Queue<StCommand>();
        Thread m_thread;

        public WidcommPortSingleThreader()
        {
            Thread t = new Thread(SingleThreader);
            t.Name = "32feetWidcommST";
#if !NETCF //SetApartmentState
            t.SetApartmentState(ApartmentState.STA);
#endif
            t.IsBackground = true;
            m_thread = t;
            m_thread.Start();
        }
#if NETCF
        ManualResetEvent _netcfEvent = new ManualResetEvent(false);
#endif

        internal T AddCommand<T>(T command) where T : StCommand
        {
            if (WidcommBtInterface.IsWidcommSingleThread
                    || Thread.CurrentThread == m_thread) {
                // Yikes the special thread is trying to offload some work!!
                Debug.Fail("Widcomm main thread calling itself!?!");
                throw new NotSupportedException("Internal error -- Widcomm main thread calling itself!?!");
            }
            lock (m_actions) {
                m_actions.Enqueue(command);
#if NETCF
                _netcfEvent.Set();
#else
                Monitor.Pulse(m_actions);
#endif
            }
            return command;
        }

        void SingleThreader()
        {
            WidcommBtInterface.IsWidcommSingleThread = true;
#if !NETCF
            while (true) {
                lock (m_actions) {
                    while (m_actions.Count == 0) {
                        Monitor.Wait(m_actions);
                    }
                    StCommand cmd = m_actions.Dequeue();
                    if (cmd is ExitCommand) {
                        break;
                    }
                    cmd.Action();
                    // Clear the command, otherwise its port reference keeps the port,
                    // which keeps the WRCStream, thus its finalizer isn't called
                    // which means this thread says alive, which keeps the command...
                    cmd = null;
                }
            }//while
#else
            while (true) {
                int count;
                lock (m_actions) {
                    count = m_actions.Count;
                }// Like Wait() must leave the lock to let the writer in!
                if (count == 0) {
                    _netcfEvent.WaitOne();
                }
                lock (m_actions) {
                    _netcfEvent.Reset();
                    count = m_actions.Count;
                    if (count == 0) {
                        Debug.Fail("Somebody else is reading from the queue!!!");
                        continue;
                    }
                    StCommand cmd = m_actions.Dequeue();
                    if (cmd is ExitCommand) {
                        break;
                    }
                    cmd.Action();
                    // Clear the command, otherwise its port reference keeps the port,
                    // which keeps the WRCStream, thus its finalizer isn't called
                    // which means this thread says alive, which keeps the command...
                    cmd = null;
                }
            }//while
#endif
        }

        internal abstract class StCommand
        {
            // TODO Pool ManualResetEvent instances in WidcommPortSingleThreader.
            ManualResetEvent _complete = new ManualResetEvent(false);
            Exception _error;


            [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
                Justification = "We rethrow it on the caller.")]
            internal void Action()
            {
                try {
                    ActionCore();
                } catch (Exception ex) {
                    _error = ex;
                } finally {
                    _complete.Set();
                }
            }

            protected abstract void ActionCore();

            public Exception Error { get { return _error; } }

            internal void WaitCompletion()
            {
                _complete.WaitOne();
                _complete.Close();
                if (Error != null)
                    throw new System.Reflection.TargetInvocationException(Error);
            }
        }

        internal sealed class ExitCommand : StCommand
        {
            protected override void ActionCore()
            { //NOP
            }
        }

        internal abstract class PortCommand : StCommand
        {
            IRfcommPort _port;
            protected IRfcommPort Port { get { return _port; } }

            public PortCommand(IRfcommPort port)
            {
                _port = port;
            }
        }

        internal sealed class PortWriteCommand : PortCommand
        {
            byte[] _data;
            ushort _lenToWrite, _lenWritten;
            PORT_RETURN_CODE _result;

            public PortWriteCommand(byte[] data, ushort lenToWrite, IRfcommPort port)
                : base(port)
            {
                _data = data;
                _lenToWrite = lenToWrite;
            }

            protected override void ActionCore()
            {
                _result = Port.Write(_data, _lenToWrite, out _lenWritten);
            }

            private new void WaitCompletion()
            {
                throw new NotSupportedException("Use WaitCompletion(out ushort lenWritten).");
            }

            internal PORT_RETURN_CODE WaitCompletion(out ushort lenWritten)
            {
                base.WaitCompletion();
                lenWritten = _lenWritten;
                return _result;
            }
        }

        internal sealed class PortCreateCommand : PortCommand
        {
            public PortCreateCommand(IRfcommPort port)
                : base(port)
            {
            }

            protected override void ActionCore()
            {
                Port.Create();
            }
        }

        internal sealed class OpenServerCommand : PortCommand
        {
            byte _scn;
            PORT_RETURN_CODE _result;

            public OpenServerCommand(byte scn, IRfcommPort port)
                : base(port)
            {
                _scn = scn;
            }

            public new PORT_RETURN_CODE WaitCompletion()
            {
                base.WaitCompletion();
                return _result;
            }

            protected override void ActionCore()
            {
                _result = Port.OpenServer(_scn);
            }
        }

        internal sealed class OpenClientCommand : PortCommand
        {
            byte _scn;
            byte[] _address;
            PORT_RETURN_CODE _result;

            public OpenClientCommand(byte scn, byte[] address, IRfcommPort port)
                : base(port)
            {
                _address = address;
                _scn = scn;
            }

            public new PORT_RETURN_CODE WaitCompletion()
            {
                base.WaitCompletion();
                return _result;
            }

            protected override void ActionCore()
            {
                _result = Port.OpenClient(_scn, _address);
            }
        }

        internal sealed class PortCloseCommand : PortCommand
        {
            public PortCloseCommand(IRfcommPort port)
                : base(port)
            {
            }

            protected override void ActionCore()
            {
                Port.Close();
            }
        }

        internal sealed class MiscNoReturnCommand : StCommand
        {
            ThreadStart _dlgt;

            public MiscNoReturnCommand(ThreadStart dlgt)
            {
                _dlgt = dlgt;
            }

            protected override void ActionCore()
            {
                _dlgt();
            }
        }

        internal delegate TResult Func<TResult>();

        internal sealed class MiscReturnCommand<TResult> : StCommand
        {
            Func<TResult> _dlgt;
            TResult _result;

            public MiscReturnCommand(Func<TResult> dlgt)
            {
                _dlgt = dlgt;
            }

            protected override void ActionCore()
            {
                _result = _dlgt();
            }

            public new TResult WaitCompletion()
            {
                base.WaitCompletion();
                return _result;
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public void Dispose(bool disposing)
        {
            // We can safely do this as Queue is not finalizable and our reference
            // keeps it alive.  The only danger could be if some blocked thread is
            // holding the lock BUT THAT'S ONLY US!
            AddCommand(new ExitCommand());
        }

        #endregion
    }
}
#endif
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.