2 // This file is part of the LWES .NET Binding (LWES.net)
4 // COPYRIGHT© 2009, Phillip Clark (cerebralkungfu[at*g mail[dot*com)
5 // original .NET implementation
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/>.
24 using System
.Threading
;
27 /// Contains utility methods.
29 public static class Util
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'
44 /// Converts an array of bytes to an octet string
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
);
54 for (int i
= first
; i
< (offset
+ len
); i
++ )
57 if (i
> first
) builder
.Append(' ');
58 builder
.Append(__nibbleHex
[b
>> 4]);
59 builder
.Append(__nibbleHex
[b
& 0x0F]);
61 return builder
.ToString();
65 /// Disposes of the referenced item and sets its value to null.
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
80 /// Initializes a referenced variable if it is not already initialized.
81 /// Uses the default constroctur for variable type T.
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()
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
;
100 /// Initializes a referenced variable if it is not already initialized. Uses
101 /// the <paramref name="factoryDelegate"/> to create the instance if necessary.
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
)
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
;
123 /// Initializes a referenced variable if it is not already initialized. Uses
124 /// the <paramref name="factoryDelegate"/> to create the instance if necessary.
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
)
134 if (lck
== null) throw new ArgumentNullException("lck");
135 if (factoryDelegate
== null) throw new ArgumentNullException("factoryDelegate");
137 if (variable
== null)
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
;
154 /// Initializes a referenced variable if it is not already initialized.
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>
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.
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)
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
;
183 /// Initializes a referenced variable if it is not already initialized.
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>
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.
198 public static T NonBlockingLazyInitializeVolatile
<T
>(ref object variable
, Func
<T
> factoryDelegate
)
201 if (factoryDelegate
== null) throw new ArgumentNullException("factoryDelegate");
203 T currentValue
= (T
)Thread
.VolatileRead(ref variable
);
204 if (currentValue
!= null)
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
;