From f07cc5b9060b026c1074683f381510ed379dd35c Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Thu, 23 Nov 2017 13:06:39 +0100 Subject: [PATCH] WIP --- ArgumentReader.cs | 37 +++++++++ Array.cs | 20 +++++ ConstructableObject.cs | 36 ++++++++ DirectoryExtensions.cs | 15 ++++ ExtendableThreadPool.cs | 174 +++++++++++++++++++++++++++++++++++++++ HexString.cs | 4 + IConstructorArguments.cs | 8 ++ LockFile.cs | 78 ++++++++++++++++++ ObjectExtensions.cs | 10 +++ Pair.cs | 21 +++++ StreamExtensions.cs | 25 ++++++ sharp.extensions.csproj | 14 +++- 12 files changed, 440 insertions(+), 2 deletions(-) create mode 100644 ArgumentReader.cs create mode 100644 ConstructableObject.cs create mode 100644 DirectoryExtensions.cs create mode 100644 ExtendableThreadPool.cs create mode 100644 IConstructorArguments.cs create mode 100644 LockFile.cs create mode 100644 ObjectExtensions.cs create mode 100644 Pair.cs create mode 100644 StreamExtensions.cs diff --git a/ArgumentReader.cs b/ArgumentReader.cs new file mode 100644 index 0000000..c290c50 --- /dev/null +++ b/ArgumentReader.cs @@ -0,0 +1,37 @@ +using System; +namespace sharp.extensions +{ + public class ArgumentReader + { + int current; + string[] arguments; + + public ArgumentReader(String[] arguments) + { + this.arguments = arguments; + this.current = 0; + } + + public String Current { get { return this.arguments[this.current]; } } + public String Next() { MoveNext(); return Current; } + + public bool MoveNext(){ + this.current++; + return this.current < this.arguments.Length; + } + + public string[] NextFollowing(int n) + { + string[] result = this.arguments.Segment(this.current + 1, n); + this.current += result.Length; + return result; + + return new string[0]; + } + + public string[] Reminder(){ + return this.arguments.Segment(this.current+1); + } + + } +} diff --git a/Array.cs b/Array.cs index 6a1b047..07c6374 100644 --- a/Array.cs +++ b/Array.cs @@ -1,4 +1,6 @@ using System; +using System.Runtime.CompilerServices; +using System.Collections.Generic; namespace sharp.extensions { public static class ArrayExtension @@ -46,6 +48,9 @@ namespace sharp.extensions } public static T[] Segment(this T[] source,int start,int len){ T[] temp = new T[len]; + if ((start + len) > source.Length){ + len = source.Length - start; + } Array.Copy(source,start,temp,0,len); return temp; } @@ -82,5 +87,20 @@ namespace sharp.extensions return Insert(a, insert, start, insert.Length); } + public static T[] Combine(this T[] a,T[] b){ + T[] r = new T[a.Length + b.Length]; + Array.Copy(a,r,a.Length); + Array.Copy(b,0,r,a.Length,b.Length); + return r; + } + + public static T[] Remove(this T[] a,T[] b){ + List rl = new List(a); + foreach (T element in b){ + rl.Remove(element); + } + return rl.ToArray(); + } + } } diff --git a/ConstructableObject.cs b/ConstructableObject.cs new file mode 100644 index 0000000..649571b --- /dev/null +++ b/ConstructableObject.cs @@ -0,0 +1,36 @@ +using System; +using System.Linq; +using System.Reflection; +namespace sharp.extensions +{ + public class ConstructableObject + { + public string AssemblyName; + public string TypeName; + public object[] ConstructorArguments; + + public ConstructableObject(){ + } + + public ConstructableObject(object o) + { + Type t = o.GetType(); + + TypeName = t.FullName; + AssemblyName = t.Assembly.FullName; + + if (t.GetInterfaces().Contains(typeof(IConstructorArguments))){ + this.ConstructorArguments = ((IConstructorArguments)o).getConstructorArguments(); + } else { + this.ConstructorArguments = new object[0]; + } + } + + public object Construct(){ + Assembly assy = Assembly.Load(AssemblyName); + Type t = assy.GetType(TypeName); + object o = Activator.CreateInstance(t, ConstructorArguments); + return o; + } + } +} diff --git a/DirectoryExtensions.cs b/DirectoryExtensions.cs new file mode 100644 index 0000000..4da32e3 --- /dev/null +++ b/DirectoryExtensions.cs @@ -0,0 +1,15 @@ +using System; +using System.IO; +namespace sharp.extensions +{ + public static class DirectoryExtensions + { + + public static void EnsureDirectoryExists(string path){ + if (!Directory.Exists(path)){ + Directory.CreateDirectory(path); + } + } + + } +} diff --git a/ExtendableThreadPool.cs b/ExtendableThreadPool.cs new file mode 100644 index 0000000..0078e13 --- /dev/null +++ b/ExtendableThreadPool.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using System.Linq; +namespace sharp.extensions +{ + public delegate void TaskDelegate(); + + public class ExtendableThreadPool + { + Stack availableThreads = new Stack(); + List activeThreads = new List(); + + Queue queuedTasks = new Queue(); + + public static ThreadLocal CurrentExtendedThread { get; private set; } = new ThreadLocal(); + + public int MaximumConcurrentThreads { get; set; } = -1; + + public ExtendableThreadPool() + { + } + + public void QueueTask(TaskDelegate task){ + lock(this) + { + queuedTasks.Enqueue(task); + SignalQueue(); + } + } + + private void SignalQueue(){ + ExtendableThread st; + + lock (this){ + if (availableThreads.Count > 0){ + st = availableThreads.Pop(); + Monitor.Enter(st); + Monitor.Pulse(st); + Monitor.Exit(st); + } else { + st = new ExtendableThread(this); + } + } + } + + private TaskDelegate fetchTask(){ + lock (this){ + if (queuedTasks.Count == 0){ + return null; + } else { + return queuedTasks.Dequeue(); + } + } + } + + protected void InvokeTaskDelegate(TaskDelegate task) + { + try + { + task.Invoke(); + } + catch (Exception e) + { + Console.WriteLine("InvokeTaskDelegate:t Task threw exception: {0}", e.ToString()); + } + } + + public class ExtendableThread + { + Thread thread; + bool requestExit; + bool isReady; + + public ExtendableThreadPool Pool { get; private set; } + + public ExtendableThread(ExtendableThreadPool pool) + { + Pool = pool; + thread = new Thread(worker); + thread.Start(); + } + + public bool IsReady { + get + { + lock (this){ + return isReady; + } + } + } + + public bool ExitRequested { + get { lock(this) { return requestExit; } } + } + + protected void InvokeTaskDelegate(TaskDelegate task) + { + Pool.InvokeTaskDelegate(task); + } + + private void worker(){ + ExtendableThreadPool.CurrentExtendedThread.Value = this; + + bool taskAvailable = true; + + while (!ExitRequested){ + TaskDelegate t; + + while ((t = Pool.fetchTask()) != null) + { + if (t != null) + { + InvokeTaskDelegate(t); + } + } + + + lock(Pool) + { + Pool.activeThreads.Remove(this); + Pool.availableThreads.Push(this); + } + + + lock(this) + { + isReady = true; + + while (!Monitor.Wait(this, 250) && !ExitRequested) { } + + if (ExitRequested) + { + break; + } + } + lock (Pool) + { + Pool.activeThreads.Add(this); + } + + } + + lock(this){ + Monitor.Pulse(this); + isReady = false; + } + } + + public void Stop() + { + lock (this) + { + requestExit = true; + } + } + public void Stop(int timeoutms) + { + lock (this) + { + requestExit = true; + Monitor.Wait(this, timeoutms); + if (thread.IsAlive){ + thread.Abort(); + } + } + } + + } + + + } +} diff --git a/HexString.cs b/HexString.cs index 7261003..317e66a 100644 --- a/HexString.cs +++ b/HexString.cs @@ -5,6 +5,10 @@ namespace sharp.extensions { public class HexString { + public static byte[] toBytes(char[] hexstring){ + return toBytes(new String(hexstring)); + } + public static byte[] toBytes(string hexstring) { byte[] bytes = new byte[hexstring.Length >> 1]; diff --git a/IConstructorArguments.cs b/IConstructorArguments.cs new file mode 100644 index 0000000..ab16173 --- /dev/null +++ b/IConstructorArguments.cs @@ -0,0 +1,8 @@ +using System; +namespace sharp.extensions +{ + public interface IConstructorArguments + { + object[] getConstructorArguments(); + } +} diff --git a/LockFile.cs b/LockFile.cs new file mode 100644 index 0000000..16ddec8 --- /dev/null +++ b/LockFile.cs @@ -0,0 +1,78 @@ +using System; +using System.IO; +using System.Threading; +using System.Text; +using System.Diagnostics; +namespace sharp.extensions +{ + public class LockFile + { + public string LockFileName { get; private set; } + public bool IsLocked { get; private set; } + + public int LockCount { get; private set; } + + public LockFile(string filename) + { + this.LockFileName = filename; + this.LockCount = 0; + } + + public void Lock() + { + if (IsLocked){ + LockCount++; + return; + } + + int retries = 3; + + Console.WriteLine("wait on lock file {0}", LockFileName); + + for (; retries > 0; retries--) + { + while (File.Exists(LockFileName)) + { + Thread.Sleep(250); + } + try + { + FileStream ls = new FileStream(LockFileName, FileMode.CreateNew); + byte[] pid = Encoding.UTF8.GetBytes(Process.GetCurrentProcess().Id.ToString()); + ls.Write(pid, 0, pid.Length); + ls.Close(); + IsLocked = true; + LockCount = 1; + + Console.WriteLine("lock acquired"); + return; + } + catch (IOException ioe) + { + } + } + ThrowIfUnlocked(); + } + + public void Unlock() + { + if (IsLocked) + { + LockCount--; + + if (LockCount == 0) + { + File.Delete(LockFileName); + IsLocked = false; + } + } + } + + public void ThrowIfUnlocked(){ + if (!IsLocked){ + throw new Exception("Lockfile is not locked"); + } + } + + } +} diff --git a/ObjectExtensions.cs b/ObjectExtensions.cs new file mode 100644 index 0000000..6acf6c2 --- /dev/null +++ b/ObjectExtensions.cs @@ -0,0 +1,10 @@ +using System; +namespace sharp.extensions +{ + public static class ObjectExtensions + { + public static bool IsNull(this object o){ + return (o == null); + } + } +} diff --git a/Pair.cs b/Pair.cs new file mode 100644 index 0000000..424523d --- /dev/null +++ b/Pair.cs @@ -0,0 +1,21 @@ +using System; +namespace sharp.extensions +{ + public class Pair + { + public T Item1 { get; set; } + public T Item2 { get; set; } + + public Pair(T i1,T i2) + { + Item1 = i1; + Item2 = i2; + } + + public override string ToString() + { + return string.Format("[Pair: Item1={0}, Item2={1}]", Item1, Item2); + } + + } +} diff --git a/StreamExtensions.cs b/StreamExtensions.cs new file mode 100644 index 0000000..f8ad3ca --- /dev/null +++ b/StreamExtensions.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; +using System.Text; + +namespace sharp.extensions +{ + public static class StreamExtensions + { + static ASCIIEncoding ascii = new ASCIIEncoding(); + + public static string ReadLine(this Stream stream){ + MemoryStream m = new MemoryStream(); + int by; + + while ((by = stream.ReadByte()) != 0x0a){ + if (by != 0x0d){ + m.WriteByte((byte)by); + } + } + + return ascii.GetString(m.GetBuffer(),0,(int)m.Length); + } + + } +} diff --git a/sharp.extensions.csproj b/sharp.extensions.csproj index 8de292c..da07a2d 100644 --- a/sharp.extensions.csproj +++ b/sharp.extensions.csproj @@ -7,7 +7,7 @@ Library sharp.extensions sharp.extensions - v4.5 + v4.7 true @@ -18,6 +18,7 @@ prompt 4 false + x64 true @@ -40,6 +41,15 @@ + + + + + + + + + - \ No newline at end of file +