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