-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Experimenting with encoding unmanged structs as blobs
- Loading branch information
Showing
10 changed files
with
199 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
using System; | ||
using System.Buffers; | ||
using System.Runtime.InteropServices; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace bhl { | ||
|
||
public class Blob<T> : IValRefcounted where T : unmanaged | ||
{ | ||
internal Pool<Blob<T>> pool; | ||
|
||
//NOTE: -1 means it's in released state, | ||
// public only for quick inspection | ||
internal int _refs; | ||
|
||
public int refs => _refs; | ||
|
||
internal byte[] data; | ||
|
||
static int Size = Marshal.SizeOf<T>(); | ||
|
||
static class PoolHolder<T1> where T1 : unmanaged | ||
{ | ||
public static System.Threading.ThreadLocal<Pool<Blob<T1>>> pool = | ||
new System.Threading.ThreadLocal<Pool<Blob<T1>>>(() => | ||
{ | ||
return new Pool<Blob<T1>>(); | ||
}); | ||
} | ||
|
||
static public Blob<T> New(ref T val) | ||
{ | ||
var pool = PoolHolder<T>.pool.Value; | ||
|
||
Blob<T> blob = null; | ||
if(pool.stack.Count == 0) | ||
{ | ||
++pool.miss; | ||
blob = new Blob<T>(); | ||
} | ||
else | ||
{ | ||
++pool.hits; | ||
blob = pool.stack.Pop(); | ||
} | ||
|
||
var data = ArrayPool<byte>.Shared.Rent(Size); | ||
|
||
ref var valRef = ref Unsafe.As<byte, T>(ref data[0]); | ||
valRef = val; | ||
|
||
blob._refs = 1; | ||
blob.data = data; | ||
blob.pool = pool; | ||
|
||
return blob; | ||
} | ||
|
||
public ref T Value => ref Unsafe.As<byte, T>(ref data[0]); | ||
|
||
public void Retain() | ||
{ | ||
if(_refs == -1) | ||
throw new Exception("Invalid state(-1)"); | ||
++_refs; | ||
} | ||
|
||
public void Release() | ||
{ | ||
if(_refs == -1) | ||
throw new Exception("Invalid state(-1)"); | ||
if(_refs == 0) | ||
throw new Exception("Double free(0)"); | ||
|
||
--_refs; | ||
if(_refs == 0) | ||
Del(this); | ||
} | ||
|
||
static void Del(Blob<T> blob) | ||
{ | ||
if(blob._refs != 0) | ||
throw new Exception("Freeing invalid object, refs " + blob._refs); | ||
|
||
blob._refs = -1; | ||
ArrayPool<byte>.Shared.Return(blob.data); | ||
|
||
blob.pool.stack.Push(blob); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System.Collections.Generic; | ||
|
||
namespace bhl { | ||
|
||
public class Pool<T> where T : class | ||
{ | ||
internal Stack<T> stack = new Stack<T>(); | ||
internal int hits; | ||
internal int miss; | ||
|
||
public int HitCount { | ||
get { return hits; } | ||
} | ||
|
||
public int MissCount { | ||
get { return miss; } | ||
} | ||
|
||
public int IdleCount { | ||
get { return stack.Count; } | ||
} | ||
|
||
public int BusyCount { | ||
get { return miss - IdleCount; } | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using bhl; | ||
using Xunit; | ||
|
||
public class TestBlobs : BHL_TestBase | ||
{ | ||
public struct StructBlob | ||
{ | ||
public int x; | ||
public int y; | ||
public int z; | ||
} | ||
|
||
[Fact] | ||
public void TestBlob() | ||
{ | ||
var val = new StructBlob(); | ||
val.x = 1; | ||
val.y = 10; | ||
val.z = 100; | ||
|
||
var blob = Blob<StructBlob>.New(ref val); | ||
|
||
AssertEqual(1, blob.Value.x); | ||
AssertEqual(10, blob.Value.y); | ||
AssertEqual(100, blob.Value.z); | ||
|
||
blob.Value.y = 30; | ||
AssertEqual(30, blob.Value.y); | ||
|
||
blob.Release(); | ||
} | ||
} |