@@ -29,41 +29,40 @@ protected BaseClient(BaseClientConfiguration config)
29
29
}
30
30
}
31
31
32
- protected async Task < string ? > Command ( IntPtr [ ] args , int argsCount , RequestType requestType )
32
+ protected async Task < T > Command < T > ( string [ ] arguments , RequestType requestType ) where T : class ?
33
33
{
34
+ IntPtr [ ] args = _arrayPool . Rent ( arguments . Length ) ;
35
+ for ( int i = 0 ; i < arguments . Length ; i ++ )
36
+ {
37
+ args [ i ] = Marshal . StringToHGlobalAnsi ( arguments [ i ] ) ;
38
+ }
34
39
// We need to pin the array in place, in order to ensure that the GC doesn't move it while the operation is running.
35
40
GCHandle pinnedArray = GCHandle . Alloc ( args , GCHandleType . Pinned ) ;
36
41
IntPtr pointer = pinnedArray . AddrOfPinnedObject ( ) ;
37
- Message < string > message = _messageContainer . GetMessageForCall ( args , argsCount ) ;
38
- CommandFfi ( _clientPointer , ( ulong ) message . Index , ( int ) requestType , pointer , ( uint ) argsCount ) ;
39
- string ? result = await message ;
42
+ Message message = _messageContainer . GetMessageForCall < T > ( args ) ;
43
+ CommandFfi ( _clientPointer , ( ulong ) message . Index , ( int ) requestType , pointer , ( uint ) arguments . Length ) ;
44
+ for ( int i = 0 ; i < arguments . Length ; i ++ )
45
+ {
46
+ Marshal . FreeHGlobal ( args [ i ] ) ;
47
+ }
40
48
pinnedArray . Free ( ) ;
41
- return result ;
42
- }
43
-
44
- public async Task < string ? > Set ( string key , string value )
45
- {
46
- IntPtr [ ] args = _arrayPool . Rent ( 2 ) ;
47
- args [ 0 ] = Marshal . StringToHGlobalAnsi ( key ) ;
48
- args [ 1 ] = Marshal . StringToHGlobalAnsi ( value ) ;
49
- string ? result = await Command ( args , 2 , RequestType . Set ) ;
50
49
_arrayPool . Return ( args ) ;
51
- return result ;
50
+ #pragma warning disable CS8603 // Possible null reference return.
51
+ return await message as T ;
52
+ #pragma warning restore CS8603 // Possible null reference return.
52
53
}
53
54
55
+ public async Task < string > Set ( string key , string value )
56
+ => await Command < string > ( [ key , value ] , RequestType . Set ) ;
57
+
54
58
public async Task < string ? > Get ( string key )
55
- {
56
- IntPtr [ ] args = _arrayPool . Rent ( 1 ) ;
57
- args [ 0 ] = Marshal . StringToHGlobalAnsi ( key ) ;
58
- string ? result = await Command ( args , 1 , RequestType . Get ) ;
59
- _arrayPool . Return ( args ) ;
60
- return result ;
61
- }
59
+ => await Command < string ? > ( [ key ] , RequestType . Get ) ;
62
60
63
61
private readonly object _lock = new ( ) ;
64
62
65
63
public void Dispose ( )
66
64
{
65
+ GC . SuppressFinalize ( this ) ;
67
66
lock ( _lock )
68
67
{
69
68
if ( _clientPointer == IntPtr . Zero )
@@ -79,14 +78,14 @@ public void Dispose()
79
78
#endregion public methods
80
79
81
80
#region private methods
82
-
81
+ // TODO rework the callback to handle other response types
83
82
private void SuccessCallback ( ulong index , IntPtr str )
84
83
{
85
84
string ? result = str == IntPtr . Zero ? null : Marshal . PtrToStringAnsi ( str ) ;
86
85
// Work needs to be offloaded from the calling thread, because otherwise we might starve the client's thread pool.
87
86
_ = Task . Run ( ( ) =>
88
87
{
89
- Message < string > message = _messageContainer . GetMessage ( ( int ) index ) ;
88
+ Message message = _messageContainer . GetMessage ( ( int ) index ) ;
90
89
message . SetResult ( result ) ;
91
90
} ) ;
92
91
}
@@ -95,7 +94,7 @@ private void FailureCallback(ulong index) =>
95
94
// Work needs to be offloaded from the calling thread, because otherwise we might starve the client's thread pool.
96
95
Task . Run ( ( ) =>
97
96
{
98
- Message < string > message = _messageContainer . GetMessage ( ( int ) index ) ;
97
+ Message message = _messageContainer . GetMessage ( ( int ) index ) ;
99
98
message . SetException ( new Exception ( "Operation failed" ) ) ;
100
99
} ) ;
101
100
@@ -114,7 +113,7 @@ private void FailureCallback(ulong index) =>
114
113
115
114
/// Raw pointer to the underlying native client.
116
115
private IntPtr _clientPointer ;
117
- private readonly MessageContainer < string > _messageContainer = new ( ) ;
116
+ private readonly MessageContainer _messageContainer = new ( ) ;
118
117
private readonly ArrayPool < IntPtr > _arrayPool = ArrayPool < IntPtr > . Shared ;
119
118
120
119
#endregion private fields
0 commit comments