2
2
using System . Diagnostics ;
3
3
using System . Globalization ;
4
4
using System . Runtime . InteropServices ;
5
+ using Interlocked = System . Threading . Interlocked ;
5
6
6
7
namespace LibGit2Sharp . Core . Handles
7
8
{
@@ -11,10 +12,15 @@ internal abstract class SafeHandleBase : SafeHandle
11
12
private readonly string trace ;
12
13
#endif
13
14
15
+ /// <summary>
16
+ /// This is set to non-zero when <see cref="NativeMethods.AddHandle"/> has
17
+ /// been called for this handle.
18
+ /// </summary>
19
+ private int registered ;
20
+
14
21
protected SafeHandleBase ( )
15
22
: base ( IntPtr . Zero , true )
16
23
{
17
- NativeMethods . AddHandle ( ) ;
18
24
#if LEAKS
19
25
trace = new StackTrace ( 2 , true ) . ToString ( ) ;
20
26
#endif
@@ -36,9 +42,26 @@ protected override void Dispose(bool disposing)
36
42
}
37
43
#endif
38
44
39
- public override bool IsInvalid
45
+ public override sealed bool IsInvalid
46
+ {
47
+ get
48
+ {
49
+ bool invalid = IsInvalidImpl ( ) ;
50
+ if ( ! invalid && Interlocked . CompareExchange ( ref registered , 1 , 0 ) == 0 )
51
+ {
52
+ // Call AddHandle at most 1 time for this handle, and only after
53
+ // we know that the handle is valid (i.e. ReleaseHandle will eventually
54
+ // be called).
55
+ NativeMethods . AddHandle ( ) ;
56
+ }
57
+
58
+ return invalid ;
59
+ }
60
+ }
61
+
62
+ protected virtual bool IsInvalidImpl ( )
40
63
{
41
- get { return ( handle == IntPtr . Zero ) ; }
64
+ return handle == IntPtr . Zero ;
42
65
}
43
66
44
67
protected abstract bool ReleaseHandleImpl ( ) ;
0 commit comments