Added initial documentation tree using doxygen. More tweaks on the license text ensur...
[lwes-dotnet/github-mirror.git] / Org.Lwes / Utils.cs
blob0768a9c15ef56d0b7d7a9c99d319b761ad8c0c2e
1 //
2 // This file is part of the LWES .NET Binding (LWES.net)
3 //
4 // COPYRIGHT© 2009, Phillip Clark (cerebralkungfu[at*g mail[dot*com)
5 // original .NET implementation
6 //
7 // LWES.net is free software: you can redistribute it and/or modify
8 // it under the terms of the Lesser GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
12 // LWES.net is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // Lesser GNU General Public License for more details.
17 // You should have received a copy of the Lesser GNU General Public License
18 // along with LWES.net. If not, see <http://www.gnu.org/licenses/>.
20 namespace Org.Lwes
22 using System;
23 using System.Text;
24 using System.Threading;
26 /// <summary>
27 /// Contains utility methods.
28 /// </summary>
29 public static class Util
31 #region Fields
33 static readonly char[] __nibbleHex = new char[]
35 '0', '1', '2', '3', '4', '5', '6', '7',
36 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
39 #endregion Fields
41 #region Methods
43 /// <summary>
44 /// Converts an array of bytes to an octet string
45 /// </summary>
46 /// <param name="buffer"></param>
47 /// <param name="offset"></param>
48 /// <param name="len"></param>
49 /// <returns></returns>
50 public static object BytesToOctets(byte[] buffer, int offset, int len)
52 StringBuilder builder = new StringBuilder(3 * len);
53 int first = offset;
54 for (int i = first; i < (offset + len); i++ )
56 byte b = buffer[i];
57 if (i > first) builder.Append(' ');
58 builder.Append(__nibbleHex[b >> 4]);
59 builder.Append(__nibbleHex[b & 0x0F]);
61 return builder.ToString();
64 /// <summary>
65 /// Disposes of the referenced item and sets its value to null.
66 /// </summary>
67 /// <typeparam name="T">item type T; must implement IDisposable</typeparam>
68 /// <param name="item">item to dispose</param>
69 public static void Dispose<T>(ref T item)
70 where T : class, IDisposable
72 if (item != null)
74 item.Dispose();
75 item = null;
79 /// <summary>
80 /// Initializes a referenced variable if it is not already initialized.
81 /// Uses the default constroctur for variable type T.
82 /// </summary>
83 /// <typeparam name="T">variable type T; must be a class with default constructor</typeparam>
84 /// <param name="variable">reference to the variable being initialized</param>
85 /// <returns>the value of the variable, after the lazy initialize</returns>
86 public static T LazyInitialize<T>(ref T variable)
87 where T : class, new()
89 if (variable == null)
91 T ourNewInstance = new T();
92 T instanceCreatedByOtherThread = Interlocked.CompareExchange(ref variable, ourNewInstance, null);
93 // prefer the race winner's instance... the GC will collect ours.
94 variable = (instanceCreatedByOtherThread != null) ? instanceCreatedByOtherThread : ourNewInstance;
96 return variable;
99 /// <summary>
100 /// Initializes a referenced variable if it is not already initialized. Uses
101 /// the <paramref name="factoryDelegate"/> to create the instance if necessary.
102 /// </summary>
103 /// <typeparam name="T">variable type T</typeparam>
104 /// <param name="variable">reference to the variable being initialized</param>
105 /// <param name="factoryDelegate">factory delegate</param>
106 /// <returns>the value of the variable, after the lazy initailize</returns>
107 public static T LazyInitialize<T>(ref T variable, Func<T> factoryDelegate)
108 where T : class
110 if (factoryDelegate == null) throw new ArgumentNullException("factoryDelegate");
112 if (variable == null)
114 T ourNewInstance = factoryDelegate();
115 T instanceCreatedByOtherThread = Interlocked.CompareExchange(ref variable, ourNewInstance, null);
116 // prefer the race winner's instance... the GC will collect ours.
117 variable = (instanceCreatedByOtherThread != null) ? instanceCreatedByOtherThread : ourNewInstance;
119 return variable;
122 /// <summary>
123 /// Initializes a referenced variable if it is not already initialized. Uses
124 /// the <paramref name="factoryDelegate"/> to create the instance if necessary.
125 /// </summary>
126 /// <typeparam name="T">variable type T</typeparam>
127 /// <param name="variable">reference to the variable being initialized</param>
128 /// <param name="lck">an object used as a lock if initialization is necessary</param>
129 /// <param name="factoryDelegate">factory delegate</param>
130 /// <returns>the value of the variable, after the lazy initailize</returns>
131 public static T LazyInitializeWithLock<T>(ref T variable, Object lck, Func<T> factoryDelegate)
132 where T : class
134 if (lck == null) throw new ArgumentNullException("lck");
135 if (factoryDelegate == null) throw new ArgumentNullException("factoryDelegate");
137 if (variable == null)
139 lock (lck)
140 { // double-check the lock in case we're in a race...
141 if (variable == null)
143 T ourNewInstance = factoryDelegate();
144 T instanceCreatedByOtherThread = Interlocked.CompareExchange(ref variable, ourNewInstance, null);
145 // prefer the race winner's instance... the GC will collect ours.
146 variable = (instanceCreatedByOtherThread != null) ? instanceCreatedByOtherThread : ourNewInstance;
150 return variable;
153 /// <summary>
154 /// Initializes a referenced variable if it is not already initialized.
155 /// </summary>
156 /// <typeparam name="T">variable type T; must be a class with default constructor</typeparam>
157 /// <param name="variable">reference to the variable being initialized</param>
158 /// <returns>the value of the variable, after the lazy initialize</returns>
159 /// <remarks>
160 /// This method is thread-safe and non-blocking, however, callers must be aware
161 /// that a race condition may occur during object creation. It is possible for two
162 /// instances of type T to be created by two different threads calling this method
163 /// at the same time; in such a case, the race loser will discard
164 /// its instance in favor of the race winner's instance. This is safe for most well
165 /// defined types whose constructors are side-effect free.
166 /// </remarks>
167 public static T NonBlockingLazyInitializeVolatile<T>(ref object variable)
168 where T : class, new()
170 T currentValue = (T)Thread.VolatileRead(ref variable);
171 if (currentValue != null)
173 return currentValue;
176 T ourNewInstance = new T();
177 T instanceCreatedByOtherThread = (T)Interlocked.CompareExchange(ref variable, ourNewInstance, null);
178 // prefer the race winner's instance... the GC will collect ours.
179 return (instanceCreatedByOtherThread != null) ? instanceCreatedByOtherThread : ourNewInstance;
182 /// <summary>
183 /// Initializes a referenced variable if it is not already initialized.
184 /// </summary>
185 /// <typeparam name="T">variable type T</typeparam>
186 /// <param name="variable">reference to the variable being initialized</param>
187 /// <param name="factoryDelegate">factory method that will be called upon to
188 /// create a new instance if necessary</param>
189 /// <returns>the value of the variable, after the lazy initialize</returns>
190 /// <remarks>
191 /// This method is thread-safe and non-blocking, however, callers must be aware
192 /// that a race condition may occur during object creation. It is possible for two
193 /// instances of type T to be created by two different threads calling this method
194 /// at the same time; in such a case, the race loser will discard
195 /// its instance in favor of the race winner's instance. This is safe for most well
196 /// defined types whose constructors are side-effect free.
197 /// </remarks>
198 public static T NonBlockingLazyInitializeVolatile<T>(ref object variable, Func<T> factoryDelegate)
199 where T : class
201 if (factoryDelegate == null) throw new ArgumentNullException("factoryDelegate");
203 T currentValue = (T)Thread.VolatileRead(ref variable);
204 if (currentValue != null)
206 return currentValue;
209 T ourNewInstance = factoryDelegate();
210 T instanceCreatedByOtherThread = (T)Interlocked.CompareExchange(ref variable, ourNewInstance, null);
211 // prefer the race winner's instance... the GC will collect ours.
212 return (instanceCreatedByOtherThread != null) ? instanceCreatedByOtherThread : ourNewInstance;
215 #endregion Methods