1 // =================================
  2 // Copyright (c) 2022 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System.IO;
  7 
  8 namespace System
  9 {
 10     public abstract class CounterBase
 11     {
 12         public nothrow CounterBase() : useCount(1)weakCount(1)
 13         {
 14         }
 15         suppress CounterBase(const CounterBase&);
 16         suppress void operator=(const CounterBase&);
 17         suppress CounterBase(CounterBase&&);
 18         suppress void operator=(CounterBase&&);
 19         public virtual default ~CounterBase();
 20         public abstract nothrow void Dispose();
 21         public virtual nothrow void Destruct()
 22         {
 23             delete this;
 24         }
 25         public inline nothrow void AddReference()
 26         {
 27             ++useCount;
 28             ++weakCount;
 29         }
 30         public inline nothrow void Release()
 31         {
 32             --useCount;
 33             if (useCount != 0)
 34             {
 35                 --weakCount;
 36                 return;
 37             }
 38             Dispose();
 39             WeakRelease();
 40         }
 41         public inline nothrow void WeakAddReference()
 42         {
 43             ++weakCount;
 44         }
 45         public nothrow void WeakRelease()
 46         {
 47             --weakCount;
 48             if (weakCount == 0)
 49             {
 50                 Destruct();
 51             }
 52         }
 53         public inline nothrow int GetUseCount() const
 54         {
 55             return useCount;
 56         }
 57         private int useCount;
 58         private int weakCount;
 59     }
 60     
 61     public class Counter<T> : CounterBase
 62     {
 63         private typedef Counter<T> Self;
 64 
 65         public nothrow Counter(T* ptr_) : ptr(ptr_)
 66         {
 67         }
 68         suppress Counter(const Self&);
 69         suppress void operator=(const Self&);
 70         suppress Counter(Self&&);
 71         suppress void operator=(Self&&);
 72         public override nothrow void Dispose()
 73         {
 74             delete ptr;
 75             ptr = null;
 76         }
 77         private T* ptr;
 78     }
 79     
 80     public class SharedCount<T>
 81     {
 82         private typedef Counter<T>* CounterPtrType;
 83         private typedef SharedCount<T> Self;
 84 
 85         public nothrow SharedCount() : counter(null)
 86         {
 87         }
 88         public nothrow SharedCount(T* ptr_) : counter(new Counter<T>(ptr_))
 89         {
 90         }
 91         public nothrow SharedCount(Counter<T>* counter_) : counter(counter_)
 92         {
 93             if (counter != null)
 94             {
 95                 counter->AddReference();
 96             }
 97         }
 98         public nothrow SharedCount(const Self& that) : counter(that.counter)
 99         {
100             if (counter != null)
101             {
102                 counter->AddReference();
103             }
104         }
105         public nothrow SharedCount(Self&& that) : counter(that.counter)
106         {
107             that.counter = null;
108         }
109         public nothrow SharedCount(const WeakCount<T>& that) : counter(that.GetCounter())
110         {
111             counter->AddReference();
112         }
113         public nothrow void operator=(const Self& that)
114         {
115             CounterPtrType otherCounter = that.counter;
116             if (otherCounter != null)
117             {
118                 otherCounter->AddReference();
119             }
120             if (counter != null)
121             {
122                 counter->Release();
123             }
124             counter = otherCounter;
125         }
126         public nothrow void operator=(Self&& that)
127         {
128             Swap(counterthat.counter);
129         }
130         public ~SharedCount()
131         {
132             if (counter != null)
133             {
134                 counter->Release();
135             }
136         }
137         public nothrow void Swap(Self& that)
138         {
139             CounterPtrType otherCounter = that.counter;
140             that.counter = counter;
141             counter = otherCounter;
142         }
143         public nothrow int GetUseCount() const
144         {
145             if (counter != null)
146             {
147                 return counter->GetUseCount();
148             }
149             return 0;
150         }
151         public nothrow bool IsUnique() const
152         {
153             return GetUseCount() == 1;
154         }
155         public nothrow CounterPtrType GetCounter() const
156         {
157             return counter;
158         }
159         private CounterPtrType counter;
160     }
161 
162     public nothrow bool operator==<T>(const SharedCount<T>& leftconst SharedCount<T>& right)
163     {
164         return left.GetCounter() == right.GetCounter();
165     }
166 
167     public nothrow bool operator<<T>(const SharedCount<T>& leftconst SharedCount<T>& right)
168     {
169         return left.GetCounter() < right.GetCounter();
170     }
171 
172     internal nothrow SharedCount<U> SharedCountCast<UT>(const SharedCount<T>& from)
173     {
174         return SharedCount<U>(cast<Counter<U>*>(from.GetCounter()));
175     }
176     
177     public class WeakCount<T>
178     {
179         private typedef Counter<T>* CounterPtrType;
180         private typedef WeakCount<T> Self;
181 
182         public nothrow WeakCount() : counter(null)
183         {
184         }
185         public nothrow WeakCount(const Self& that) : counter(that.counter)
186         {
187             if (counter != null)
188             {
189                 counter->WeakAddReference();
190             }
191         }
192         public nothrow WeakCount(Self&& that) : counter(that.counter)
193         {
194             that.counter = null;
195         }
196         public nothrow WeakCount(const SharedCount<T>& that) : counter(that.GetCounter())
197         {
198             if (counter != null)
199             {
200                 counter->WeakAddReference();
201             }
202         }
203         public ~WeakCount()
204         {
205             if (counter != null)
206             {
207                 counter->WeakRelease();
208             }
209         }
210         public nothrow void operator=(const SharedCount<T>& that)
211         {
212             CounterPtrType otherCounter = that.GetCounter();
213             if (otherCounter != null)
214             {
215                 otherCounter->WeakAddReference();
216             }
217             if (counter != null)
218             {
219                 counter->WeakRelease();
220             }
221             counter = otherCounter;
222         }
223         public nothrow void operator=(const Self& that)
224         {
225             CounterPtrType otherCounter = that.counter;
226             if (otherCounter != null)
227             {
228                 otherCounter->WeakAddReference();
229             }
230             if (counter != null)
231             {
232                 counter->WeakRelease();
233             }
234             counter = otherCounter;
235         }
236         public nothrow void operator=(Self&& that)
237         {
238             Swap(counterthat.counter);
239         }
240         public nothrow void Swap(Self& that)
241         {
242             CounterPtrType otherCounter = that.counter;
243             that.counter = counter;
244             counter = otherCounter;
245         }
246         public nothrow int GetUseCount() const
247         {
248             if (counter != null)
249             {
250                 return counter->GetUseCount();
251             }
252             return 0;
253         }
254         public nothrow CounterPtrType GetCounter() const
255         {
256             return counter;
257         }
258         private CounterPtrType counter;
259     }
260     
261     public nothrow bool operator==<T>(const WeakCount<T>& leftconst WeakCount<T>& right)
262     {
263         return left.GetCounter() == right.GetCounter();
264     }
265 
266     public nothrow bool operator<<T>(const WeakCount<T>& leftconst WeakCount<T>& right)
267     {
268         return left.GetCounter() < right.GetCounter();
269     }
270 
271     public class SharedPtr<T>
272     {
273         private typedef SharedPtr<T> Self;
274         private typedef SharedCount<T> CountType;
275 
276         public nothrow SharedPtr() : ptr(null)count()
277         {
278         }
279         public explicit nothrow SharedPtr(T* ptr_) : ptr(ptr_)count(ptr)
280         {
281             EnableSharedFromThis(ptr_ptr_count);
282         }
283         public nothrow SharedPtr(T* ptr_const CountType& count_) : ptr(ptr_)count(count_)
284         {
285         }
286         public nothrow SharedPtr(const Self& that) : ptr(that.ptr)count(that.count)
287         {
288         }
289         public nothrow SharedPtr(Self&& that) : ptr(that.ptr)count(Rvalue(that.count))
290         {
291             that.ptr = null;
292         }
293         public nothrow SharedPtr(const WeakPtr<T>& that) : ptr()count(that.GetCount())
294         {
295             ptr = that.Get();
296         }
297         public nothrow void Reset()
298         {
299             Self().Swap(*this);
300         }
301         public nothrow void Reset(T* ptr_)
302         {
303             Self(ptr_).Swap(*this);
304         }
305         public nothrow void operator=(const Self& that)
306         {
307             ptr = that.ptr;
308             count = that.count;
309         }
310         public nothrow void operator=(Self&& that)
311         {
312             Swap(ptrthat.ptr);
313             Swap(countthat.count);
314         }
315         public inline nothrow T* operator->() const
316         {
317             if (ptr == null)
318             {
319                 ThrowNullPointerException();
320             }
321             return ptr;
322         }
323         public inline nothrow T& operator*() const
324         {
325             if (ptr == null)
326             {
327                 ThrowNullPointerException();
328             }
329             return *ptr;
330         }
331         public inline nothrow T* Get() const
332         {
333             return ptr;
334         }
335         public inline nothrow const CountType& GetCount() const
336         {
337             return count;
338         }
339         public inline nothrow bool IsNull() const
340         {
341             return ptr == null;
342         }
343         public nothrow void Swap(Self& that)
344         {
345             Swap(ptrthat.ptr);
346             count.Swap(that.count);
347         }
348         public nothrow bool IsUnique() const
349         {
350             return count.IsUnique();
351         }
352         public nothrow int GetUseCount() const
353         {
354             return count.GetUseCount();
355         }
356         private T* ptr;
357         private CountType count;
358     }
359 
360     public nothrow bool operator==<T>(const SharedPtr<T>& leftconst SharedPtr<T>& right)
361     {
362         return left.Get() == right.Get();
363     }
364 
365     public nothrow bool operator<<T>(const SharedPtr<T>& leftconst SharedPtr<T>& right)
366     {
367         return left.Get() < right.Get();
368     }
369 
370     public nothrow SharedPtr<U> PtrCast<UT>(const SharedPtr<T>& from)
371     {
372         return SharedPtr<U>(cast<U*>(from.Get())SharedCountCast<U>(from.GetCount()));
373     }
374 
375     public class WeakPtr<T>
376     {
377         private typedef WeakPtr<T> Self;
378         private typedef WeakCount<T> CountType;
379 
380         public nothrow WeakPtr() : ptr(null)count()
381         {
382         }
383         public nothrow WeakPtr(const SharedPtr<T>& that) : ptr(that.Get())count(that.GetCount())
384         {
385         }
386         public nothrow WeakPtr(const Self& that) : ptr()count(that.count)
387         {
388             ptr = that.Lock().Get();
389         }
390         public default ~WeakPtr();
391         public nothrow void operator=(const Self& that)
392         {
393             ptr = that.Lock().Get();
394             count = that.count;
395         }
396         public nothrow void operator=(const SharedPtr<T>& that)
397         {
398             ptr = that.Get();
399             count = that.GetCount();
400         }
401         public nothrow int GetUseCount() const
402         {
403             return count.GetUseCount();
404         }
405         public nothrow bool IsExpired() const
406         {
407             return count.GetUseCount() == 0;
408         }
409         public nothrow SharedPtr<T> Lock() const
410         {
411             if (IsExpired())
412             {
413                 return SharedPtr<T>();
414             }
415             return SharedPtr<T>(*this);
416         }
417         public nothrow void Reset()
418         {
419             Self().Swap(*this);
420         }
421         public nothrow void Swap(Self& that)
422         {
423             Swap(ptrthat.ptr);
424             count.Swap(that.count);
425         }
426         public inline nothrow const CountType& GetCount() const
427         {
428             return count;
429         }
430         public inline nothrow T* GetPtr() const
431         {
432             return ptr;
433         }
434         public inline nothrow T* Get() const
435         {
436             return ptr;
437         }
438         public nothrow void Assign(T* ptr_const SharedCount<T>& count_)
439         {
440             ptr = ptr_;
441             count = count_;
442         }
443         private T* ptr;
444         private CountType count;
445     }
446 
447     public class ShareableFromThis<T>
448     {
449         public nothrow SharedPtr<T> GetSharedFromThis() const
450         {
451             SharedPtr<T> p(weakThis);
452             return p;
453         }
454         public nothrow WeakPtr<T>& GetWeakThis()
455         {
456             return weakThis;
457         }
458         private WeakPtr<T> weakThis;
459     }
460 
461     public inline nothrow void EnableSharedFromThis<T>(void*void*const SharedCount<T>&)
462     {
463     }
464 
465     public nothrow void EnableSharedFromThis<TU>(ShareableFromThis<T>* leftU* rightconst SharedCount<U>& count)
466     {
467         if (left != null)
468         {
469             left->GetWeakThis().Assign(cast<T*>(right)SharedCountCast<T>(count));
470         }
471     }
472 
473     [system_default="true"]
474     public TextWriter& operator<<<T>(TextWriter& writerconst SharedPtr<T>& ptr)
475     {
476         if (ptr.IsNull())
477         {
478             writer << "null";
479         }
480         else
481         {
482             const T& temp = *ptr;
483             writer << temp;
484         }
485         return writer;
486     }
487 }