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