Repository files navigation

SharedMemoryStore

SharedMemoryStore is a bounded, cross-process shared-memory key-value store for opaque binary keys, descriptors, and payloads. Its .NET, C++, and Python distributions implement the same lock-free SMS2 mapped protocol on Windows and Linux x64.

The store is intentionally small in scope. It publishes named values, provides zero-copy reservations and read leases, removes and reuses generations, exposes explicit recovery, and reports bounded diagnostics. Queueing, routing, subscriptions, persistence, serialization, and application schemas belong in the application layer.

Current releases and protocol

DistributionVersionRuntime surface
NuGet SharedMemoryStore3.0.0net10.0, C#
CMake SharedMemoryStore1.0.0C++20 and C ABI 2.0
Python shared-memory-store1.0.0Python 3.10+ over the packaged C ABI 2.0 library

All three create and read exactly one shared protocol:

magic=SMS2 layout=2.0 resource-protocol=2 required-features=7 optional-features=0

Package versions are independent from the mapped protocol identity. The canonical byte layout, resource names, feature masks, and distribution matrix live in protocol/README.md and protocol/compatibility.json.

Core properties

  • Fixed capacities are chosen before creation: slots, value bytes, descriptor bytes, key bytes, lease records, and participant records.
  • Every open handle owns one participant record. The default capacity is 64; exhaustion returns ParticipantTableFull without disturbing existing handles.
  • Publish, reserve, commit, acquire, release, remove, reclaim, recovery help, and diagnostics do not acquire a process-owned or store-wide OS lock.
  • Cold create, open, participant registration, close, and final resource cleanup use bounded platform coordination.
  • Keys are exact opaque byte sequences. Hashes select candidates, but equality always checks the complete key bytes.
  • Leases and reservations are generation-fenced. Their mapped views are valid only while the exact token and store handle remain alive.
  • The qualified atomic contract is little-endian x86-64 with naturally aligned lock-free 64-bit atomics.

C# quick start

Install the package:

dotnet add package SharedMemoryStore --version 3.0.0

Create options with the ordinary participant-aware helper:

usingSharedMemoryStore;varoptions=SharedMemoryStoreOptions.Create($"orders-{Guid.NewGuid():N}",slotCount:128,maxValueBytes:64*1024,maxDescriptorBytes:64,maxKeyBytes:64,leaseRecordCount:256,participantRecordCount:64,openMode:OpenMode.CreateNew,enableLeaseRecovery:true);StoreOpenStatusopened=MemoryStore.TryCreateOrOpen(options,outMemoryStore?store);if(opened!=StoreOpenStatus.Success||storeisnull){thrownewInvalidOperationException($"Open failed: {opened}");}using(store){byte[]key=[0x01,0x00,0x02];byte[]value=[0x10,0x00,0x20];if(store.TryPublish(key,value)!=StoreStatus.Success){thrownewInvalidOperationException("Publish failed.");}if(store.TryAcquire(key,outValueLeaselease)!=StoreStatus.Success){thrownewInvalidOperationException("Acquire failed.");}using(lease){Console.WriteLine(Convert.ToHexString(lease.ValueSpan));}StoreStatusremoved=store.TryRemove(key);if(removedis not (StoreStatus.Success or StoreStatus.RemovePending)){thrownewInvalidOperationException($"Remove failed: {removed}");}Console.WriteLine(store.ProtocolInfo);// (2, 0, 2, 7, 0)}

TryRemove makes the key logically absent at its ordering point. It returns RemovePending when a live lease or bounded cleanup still delays physical slot reuse; a later release, remove, or allocation-pressure helper may finish the reclamation.

C++ quick start

Build or install the CMake package, then consume it with:

find_package(SharedMemoryStoreCONFIGREQUIRED)
target_link_libraries(my_appPRIVATESharedMemoryStore::shared_memory_store)
#include<shared_memory_store/store.hpp>
#include<array>usingnamespaceshared_memory_store;auto options = store_options::create(
"orders", 128, 64 * 1024, 64, 64, 256, 64,
open_mode::create_or_open, true);
memory_store store;
if (memory_store::try_create_or_open(options, store) != open_status::success) {
return1;
}
const std::array<std::byte, 2> key{std::byte{1}, std::byte{2}};
const std::array<std::byte, 3> value{std::byte{7}, std::byte{8}, std::byte{9}};
if (store.try_publish(key, value) != status::success) return2;
value_lease lease;
if (store.try_acquire(key, lease) != status::success) return3;
auto borrowed = lease.value();
return lease.release() == status::success ? 0 : 4;

memory_store, value_lease, and value_reservation are move-only. Their destructors are best-effort fallbacks; explicit close, release, and abort remain the deterministic lifecycle operations.

Python quick start

Build and install the platform wheel, then use the context-managed API:

fromshared_memory_storeimportMemoryStore, OpenMode, StoreOpenStatus, StoreOptions, StoreStatusoptions=StoreOptions.create(
"orders",
slot_count=128,
max_value_bytes=64*1024,
max_descriptor_bytes=64,
max_key_bytes=64,
lease_record_count=256,
participant_record_count=64,
open_mode=OpenMode.CREATE_OR_OPEN,
enable_lease_recovery=True,
)
open_status, store=MemoryStore.open(options)
ifopen_statusisnotStoreOpenStatus.SUCCESSorstoreisNone:
raiseRuntimeError(f"open failed: {open_status}")
withstore:
ifstore.publish(b"order-1", b"payload\x00") isnotStoreStatus.SUCCESS:
raiseRuntimeError("publish failed")
acquire_status, lease=store.acquire(b"order-1")
ifacquire_statusisnotStoreStatus.SUCCESSorleaseisNone:
raiseRuntimeError(f"acquire failed: {acquire_status}")
withlease:
print(bytes(lease.value))

Python loads only the native library packaged beside its modules. A clean wheel consumer must not depend on the repository source tree or PYTHONPATH.

Waits, progress, and cancellation

Every operation accepts a no-wait, finite, or infinite policy. C# uses StoreWaitOptions, C++ uses wait_options, and Python uses WaitOptions. Finite budgets cover local retry, revalidation, helping, backoff, and any cold lifecycle wait for that call. Cancellation wins only before the operation's documented ordering point; it never rolls back an already published shared result.

StoreBusy means the call exhausted its bounded progress budget. It is a retryable contention result, not evidence of corruption and not proof that a global lock was held.

Recovery and diagnostics

Recovery is explicit and conservative. Enable it in the options, then call the lease or reservation recovery API. A record is reclaimed only when its exact participant incarnation and owner identity are safely stale. Live, changing, unsupported, or inconsistent evidence is retained and reported.

Diagnostics report the immutable five-field protocol identity plus shared capacity, slot, lease, reservation, participant, and directory facts. CAS retries, helping, contention exhaustion, invalid/stale tokens, recovery attempts, owner classifications, and status counts are local to the calling runtime or handle unless documented otherwise.

See docs/diagnostics.md for the complete distinction.

Moving an existing deployment to SMS2

There is no in-place conversion and no current client reads a noncurrent mapping to migrate it. Use application-owned authoritative data:

  1. stop publishers and prevent new readers;
  2. drain leases and reservations;
  3. close every process-local handle;
  4. remove or replace the old physical store;
  5. create a fresh SMS2 store with the intended participant-aware capacities;
  6. republish authoritative values; and
  7. start current clients.

A side-by-side cutover uses a distinct public store name. An incompatible or malformed existing mapping returns IncompatibleLayout before payload access.

Build and validation

Managed:

dotnet build SharedMemoryStore.slnx -c Release
dotnet test SharedMemoryStore.slnx -c Release
pwsh ./scripts/validate-package-consumption.ps1 -Configuration Release

Native and Python:

pwsh ./scripts/validate-native.ps1 -Configuration Release
pwsh ./scripts/validate-python.ps1 -Configuration Release

The repository also contains a deterministic protocol manifest, nine ordered runtime-pair tests, raw visibility and crash checkpoints, package-consumer tests, and Windows/Linux qualification gates.

Documentation and samples

License and project policy

SharedMemoryStore is licensed under the MIT License. See CONTRIBUTING.md, SUPPORT.md, and SECURITY.md before contributing or reporting an issue.

About

A .NET 10 shared-memory key/value store for same-host processes, with zero-copy ingest, leases, diagnostics, and runnable samples.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

SharedMemoryStore

SharedMemoryStore is a bounded, cross-process shared-memory key-value store for opaque binary keys, descriptors, and payloads. Its .NET, C++, and Python distributions implement the same lock-free SMS2 mapped protocol on Windows and Linux x64.

The store is intentionally small in scope. It publishes named values, provides zero-copy reservations and read leases, removes and reuses generations, exposes explicit recovery, and reports bounded diagnostics. Queueing, routing, subscriptions, persistence, serialization, and application schemas belong in the application layer.

Current releases and protocol

DistributionVersionRuntime surface
NuGet SharedMemoryStore3.0.0net10.0, C#
CMake SharedMemoryStore1.0.0C++20 and C ABI 2.0
Python shared-memory-store1.0.0Python 3.10+ over the packaged C ABI 2.0 library

All three create and read exactly one shared protocol:

magic=SMS2 layout=2.0 resource-protocol=2 required-features=7 optional-features=0

Package versions are independent from the mapped protocol identity. The canonical byte layout, resource names, feature masks, and distribution matrix live in protocol/README.md and protocol/compatibility.json.

Core properties

  • Fixed capacities are chosen before creation: slots, value bytes, descriptor bytes, key bytes, lease records, and participant records.
  • Every open handle owns one participant record. The default capacity is 64; exhaustion returns ParticipantTableFull without disturbing existing handles.
  • Publish, reserve, commit, acquire, release, remove, reclaim, recovery help, and diagnostics do not acquire a process-owned or store-wide OS lock.
  • Cold create, open, participant registration, close, and final resource cleanup use bounded platform coordination.
  • Keys are exact opaque byte sequences. Hashes select candidates, but equality always checks the complete key bytes.
  • Leases and reservations are generation-fenced. Their mapped views are valid only while the exact token and store handle remain alive.
  • The qualified atomic contract is little-endian x86-64 with naturally aligned lock-free 64-bit atomics.

C# quick start

Install the package:

dotnet add package SharedMemoryStore --version 3.0.0

Create options with the ordinary participant-aware helper:

usingSharedMemoryStore;varoptions=SharedMemoryStoreOptions.Create($"orders-{Guid.NewGuid():N}",slotCount:128,maxValueBytes:64*1024,maxDescriptorBytes:64,maxKeyBytes:64,leaseRecordCount:256,participantRecordCount:64,openMode:OpenMode.CreateNew,enableLeaseRecovery:true);StoreOpenStatusopened=MemoryStore.TryCreateOrOpen(options,outMemoryStore?store);if(opened!=StoreOpenStatus.Success||storeisnull){thrownewInvalidOperationException($"Open failed: {opened}");}using(store){byte[]key=[0x01,0x00,0x02];byte[]value=[0x10,0x00,0x20];if(store.TryPublish(key,value)!=StoreStatus.Success){thrownewInvalidOperationException("Publish failed.");}if(store.TryAcquire(key,outValueLeaselease)!=StoreStatus.Success){thrownewInvalidOperationException("Acquire failed.");}using(lease){Console.WriteLine(Convert.ToHexString(lease.ValueSpan));}StoreStatusremoved=store.TryRemove(key);if(removedis not (StoreStatus.Success or StoreStatus.RemovePending)){thrownewInvalidOperationException($"Remove failed: {removed}");}Console.WriteLine(store.ProtocolInfo);// (2, 0, 2, 7, 0)}

TryRemove makes the key logically absent at its ordering point. It returns RemovePending when a live lease or bounded cleanup still delays physical slot reuse; a later release, remove, or allocation-pressure helper may finish the reclamation.

C++ quick start

Build or install the CMake package, then consume it with:

find_package(SharedMemoryStoreCONFIGREQUIRED)
target_link_libraries(my_appPRIVATESharedMemoryStore::shared_memory_store)
#include<shared_memory_store/store.hpp>
#include<array>usingnamespaceshared_memory_store;auto options = store_options::create(
"orders", 128, 64 * 1024, 64, 64, 256, 64,
open_mode::create_or_open, true);
memory_store store;
if (memory_store::try_create_or_open(options, store) != open_status::success) {
return1;
}
const std::array<std::byte, 2> key{std::byte{1}, std::byte{2}};
const std::array<std::byte, 3> value{std::byte{7}, std::byte{8}, std::byte{9}};
if (store.try_publish(key, value) != status::success) return2;
value_lease lease;
if (store.try_acquire(key, lease) != status::success) return3;
auto borrowed = lease.value();
return lease.release() == status::success ? 0 : 4;

memory_store, value_lease, and value_reservation are move-only. Their destructors are best-effort fallbacks; explicit close, release, and abort remain the deterministic lifecycle operations.

Python quick start

Build and install the platform wheel, then use the context-managed API:

fromshared_memory_storeimportMemoryStore, OpenMode, StoreOpenStatus, StoreOptions, StoreStatusoptions=StoreOptions.create(
"orders",
slot_count=128,
max_value_bytes=64*1024,
max_descriptor_bytes=64,
max_key_bytes=64,
lease_record_count=256,
participant_record_count=64,
open_mode=OpenMode.CREATE_OR_OPEN,
enable_lease_recovery=True,
)
open_status, store=MemoryStore.open(options)
ifopen_statusisnotStoreOpenStatus.SUCCESSorstoreisNone:
raiseRuntimeError(f"open failed: {open_status}")
withstore:
ifstore.publish(b"order-1", b"payload\x00") isnotStoreStatus.SUCCESS:
raiseRuntimeError("publish failed")
acquire_status, lease=store.acquire(b"order-1")
ifacquire_statusisnotStoreStatus.SUCCESSorleaseisNone:
raiseRuntimeError(f"acquire failed: {acquire_status}")
withlease:
print(bytes(lease.value))

Python loads only the native library packaged beside its modules. A clean wheel consumer must not depend on the repository source tree or PYTHONPATH.

Waits, progress, and cancellation

Every operation accepts a no-wait, finite, or infinite policy. C# uses StoreWaitOptions, C++ uses wait_options, and Python uses WaitOptions. Finite budgets cover local retry, revalidation, helping, backoff, and any cold lifecycle wait for that call. Cancellation wins only before the operation's documented ordering point; it never rolls back an already published shared result.

StoreBusy means the call exhausted its bounded progress budget. It is a retryable contention result, not evidence of corruption and not proof that a global lock was held.

Recovery and diagnostics

Recovery is explicit and conservative. Enable it in the options, then call the lease or reservation recovery API. A record is reclaimed only when its exact participant incarnation and owner identity are safely stale. Live, changing, unsupported, or inconsistent evidence is retained and reported.

Diagnostics report the immutable five-field protocol identity plus shared capacity, slot, lease, reservation, participant, and directory facts. CAS retries, helping, contention exhaustion, invalid/stale tokens, recovery attempts, owner classifications, and status counts are local to the calling runtime or handle unless documented otherwise.

See docs/diagnostics.md for the complete distinction.

Moving an existing deployment to SMS2

There is no in-place conversion and no current client reads a noncurrent mapping to migrate it. Use application-owned authoritative data:

  1. stop publishers and prevent new readers;
  2. drain leases and reservations;
  3. close every process-local handle;
  4. remove or replace the old physical store;
  5. create a fresh SMS2 store with the intended participant-aware capacities;
  6. republish authoritative values; and
  7. start current clients.

A side-by-side cutover uses a distinct public store name. An incompatible or malformed existing mapping returns IncompatibleLayout before payload access.

Build and validation

Managed:

dotnet build SharedMemoryStore.slnx -c Release
dotnet test SharedMemoryStore.slnx -c Release
pwsh ./scripts/validate-package-consumption.ps1 -Configuration Release

Native and Python:

pwsh ./scripts/validate-native.ps1 -Configuration Release
pwsh ./scripts/validate-python.ps1 -Configuration Release

The repository also contains a deterministic protocol manifest, nine ordered runtime-pair tests, raw visibility and crash checkpoints, package-consumer tests, and Windows/Linux qualification gates.

Documentation and samples

License and project policy

SharedMemoryStore is licensed under the MIT License. See CONTRIBUTING.md, SUPPORT.md, and SECURITY.md before contributing or reporting an issue.

About

A .NET 10 shared-memory key/value store for same-host processes, with zero-copy ingest, leases, diagnostics, and runnable samples.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SharedMemoryStore

SharedMemoryStore is a bounded, cross-process shared-memory key-value store for opaque binary keys, descriptors, and payloads. Its .NET, C++, and Python distributions implement the same lock-free SMS2 mapped protocol on Windows and Linux x64.

The store is intentionally small in scope. It publishes named values, provides zero-copy reservations and read leases, removes and reuses generations, exposes explicit recovery, and reports bounded diagnostics. Queueing, routing, subscriptions, persistence, serialization, and application schemas belong in the application layer.

Current releases and protocol

DistributionVersionRuntime surface
NuGet SharedMemoryStore3.0.0net10.0, C#
CMake SharedMemoryStore1.0.0C++20 and C ABI 2.0
Python shared-memory-store1.0.0Python 3.10+ over the packaged C ABI 2.0 library

All three create and read exactly one shared protocol:

magic=SMS2 layout=2.0 resource-protocol=2 required-features=7 optional-features=0

Package versions are independent from the mapped protocol identity. The canonical byte layout, resource names, feature masks, and distribution matrix live in protocol/README.md and protocol/compatibility.json.

Core properties

  • Fixed capacities are chosen before creation: slots, value bytes, descriptor bytes, key bytes, lease records, and participant records.
  • Every open handle owns one participant record. The default capacity is 64; exhaustion returns ParticipantTableFull without disturbing existing handles.
  • Publish, reserve, commit, acquire, release, remove, reclaim, recovery help, and diagnostics do not acquire a process-owned or store-wide OS lock.
  • Cold create, open, participant registration, close, and final resource cleanup use bounded platform coordination.
  • Keys are exact opaque byte sequences. Hashes select candidates, but equality always checks the complete key bytes.
  • Leases and reservations are generation-fenced. Their mapped views are valid only while the exact token and store handle remain alive.
  • The qualified atomic contract is little-endian x86-64 with naturally aligned lock-free 64-bit atomics.

C# quick start

Install the package:

dotnet add package SharedMemoryStore --version 3.0.0

Create options with the ordinary participant-aware helper:

usingSharedMemoryStore;varoptions=SharedMemoryStoreOptions.Create($"orders-{Guid.NewGuid():N}",slotCount:128,maxValueBytes:64*1024,maxDescriptorBytes:64,maxKeyBytes:64,leaseRecordCount:256,participantRecordCount:64,openMode:OpenMode.CreateNew,enableLeaseRecovery:true);StoreOpenStatusopened=MemoryStore.TryCreateOrOpen(options,outMemoryStore?store);if(opened!=StoreOpenStatus.Success||storeisnull){thrownewInvalidOperationException($"Open failed: {opened}");}using(store){byte[]key=[0x01,0x00,0x02];byte[]value=[0x10,0x00,0x20];if(store.TryPublish(key,value)!=StoreStatus.Success){thrownewInvalidOperationException("Publish failed.");}if(store.TryAcquire(key,outValueLeaselease)!=StoreStatus.Success){thrownewInvalidOperationException("Acquire failed.");}using(lease){Console.WriteLine(Convert.ToHexString(lease.ValueSpan));}StoreStatusremoved=store.TryRemove(key);if(removedis not (StoreStatus.Success or StoreStatus.RemovePending)){thrownewInvalidOperationException($"Remove failed: {removed}");}Console.WriteLine(store.ProtocolInfo);// (2, 0, 2, 7, 0)}

TryRemove makes the key logically absent at its ordering point. It returns RemovePending when a live lease or bounded cleanup still delays physical slot reuse; a later release, remove, or allocation-pressure helper may finish the reclamation.

C++ quick start

Build or install the CMake package, then consume it with:

find_package(SharedMemoryStoreCONFIGREQUIRED)
target_link_libraries(my_appPRIVATESharedMemoryStore::shared_memory_store)
#include<shared_memory_store/store.hpp>
#include<array>usingnamespaceshared_memory_store;auto options = store_options::create(
"orders", 128, 64 * 1024, 64, 64, 256, 64,
open_mode::create_or_open, true);
memory_store store;
if (memory_store::try_create_or_open(options, store) != open_status::success) {
return1;
}
const std::array<std::byte, 2> key{std::byte{1}, std::byte{2}};
const std::array<std::byte, 3> value{std::byte{7}, std::byte{8}, std::byte{9}};
if (store.try_publish(key, value) != status::success) return2;
value_lease lease;
if (store.try_acquire(key, lease) != status::success) return3;
auto borrowed = lease.value();
return lease.release() == status::success ? 0 : 4;

memory_store, value_lease, and value_reservation are move-only. Their destructors are best-effort fallbacks; explicit close, release, and abort remain the deterministic lifecycle operations.

Python quick start

Build and install the platform wheel, then use the context-managed API:

fromshared_memory_storeimportMemoryStore, OpenMode, StoreOpenStatus, StoreOptions, StoreStatusoptions=StoreOptions.create(
"orders",
slot_count=128,
max_value_bytes=64*1024,
max_descriptor_bytes=64,
max_key_bytes=64,
lease_record_count=256,
participant_record_count=64,
open_mode=OpenMode.CREATE_OR_OPEN,
enable_lease_recovery=True,
)
open_status, store=MemoryStore.open(options)
ifopen_statusisnotStoreOpenStatus.SUCCESSorstoreisNone:
raiseRuntimeError(f"open failed: {open_status}")
withstore:
ifstore.publish(b"order-1", b"payload\x00") isnotStoreStatus.SUCCESS:
raiseRuntimeError("publish failed")
acquire_status, lease=store.acquire(b"order-1")
ifacquire_statusisnotStoreStatus.SUCCESSorleaseisNone:
raiseRuntimeError(f"acquire failed: {acquire_status}")
withlease:
print(bytes(lease.value))

Python loads only the native library packaged beside its modules. A clean wheel consumer must not depend on the repository source tree or PYTHONPATH.

Waits, progress, and cancellation

Every operation accepts a no-wait, finite, or infinite policy. C# uses StoreWaitOptions, C++ uses wait_options, and Python uses WaitOptions. Finite budgets cover local retry, revalidation, helping, backoff, and any cold lifecycle wait for that call. Cancellation wins only before the operation's documented ordering point; it never rolls back an already published shared result.

StoreBusy means the call exhausted its bounded progress budget. It is a retryable contention result, not evidence of corruption and not proof that a global lock was held.

Recovery and diagnostics

Recovery is explicit and conservative. Enable it in the options, then call the lease or reservation recovery API. A record is reclaimed only when its exact participant incarnation and owner identity are safely stale. Live, changing, unsupported, or inconsistent evidence is retained and reported.

Diagnostics report the immutable five-field protocol identity plus shared capacity, slot, lease, reservation, participant, and directory facts. CAS retries, helping, contention exhaustion, invalid/stale tokens, recovery attempts, owner classifications, and status counts are local to the calling runtime or handle unless documented otherwise.

See docs/diagnostics.md for the complete distinction.

Moving an existing deployment to SMS2

There is no in-place conversion and no current client reads a noncurrent mapping to migrate it. Use application-owned authoritative data:

  1. stop publishers and prevent new readers;
  2. drain leases and reservations;
  3. close every process-local handle;
  4. remove or replace the old physical store;
  5. create a fresh SMS2 store with the intended participant-aware capacities;
  6. republish authoritative values; and
  7. start current clients.

A side-by-side cutover uses a distinct public store name. An incompatible or malformed existing mapping returns IncompatibleLayout before payload access.

Build and validation

Managed:

dotnet build SharedMemoryStore.slnx -c Release
dotnet test SharedMemoryStore.slnx -c Release
pwsh ./scripts/validate-package-consumption.ps1 -Configuration Release

Native and Python:

pwsh ./scripts/validate-native.ps1 -Configuration Release
pwsh ./scripts/validate-python.ps1 -Configuration Release

The repository also contains a deterministic protocol manifest, nine ordered runtime-pair tests, raw visibility and crash checkpoints, package-consumer tests, and Windows/Linux qualification gates.

Documentation and samples

License and project policy

SharedMemoryStore is licensed under the MIT License. See CONTRIBUTING.md, SUPPORT.md, and SECURITY.md before contributing or reporting an issue.

About

A .NET 10 shared-memory key/value store for same-host processes, with zero-copy ingest, leases, diagnostics, and runnable samples.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SharedMemoryStore

SharedMemoryStore is a bounded, cross-process shared-memory key-value store for opaque binary keys, descriptors, and payloads. Its .NET, C++, and Python distributions implement the same lock-free SMS2 mapped protocol on Windows and Linux x64.

The store is intentionally small in scope. It publishes named values, provides zero-copy reservations and read leases, removes and reuses generations, exposes explicit recovery, and reports bounded diagnostics. Queueing, routing, subscriptions, persistence, serialization, and application schemas belong in the application layer.

Current releases and protocol

DistributionVersionRuntime surface
NuGet SharedMemoryStore3.0.0net10.0, C#
CMake SharedMemoryStore1.0.0C++20 and C ABI 2.0
Python shared-memory-store1.0.0Python 3.10+ over the packaged C ABI 2.0 library

All three create and read exactly one shared protocol:

magic=SMS2 layout=2.0 resource-protocol=2 required-features=7 optional-features=0

Package versions are independent from the mapped protocol identity. The canonical byte layout, resource names, feature masks, and distribution matrix live in protocol/README.md and protocol/compatibility.json.

Core properties

  • Fixed capacities are chosen before creation: slots, value bytes, descriptor bytes, key bytes, lease records, and participant records.
  • Every open handle owns one participant record. The default capacity is 64; exhaustion returns ParticipantTableFull without disturbing existing handles.
  • Publish, reserve, commit, acquire, release, remove, reclaim, recovery help, and diagnostics do not acquire a process-owned or store-wide OS lock.
  • Cold create, open, participant registration, close, and final resource cleanup use bounded platform coordination.
  • Keys are exact opaque byte sequences. Hashes select candidates, but equality always checks the complete key bytes.
  • Leases and reservations are generation-fenced. Their mapped views are valid only while the exact token and store handle remain alive.
  • The qualified atomic contract is little-endian x86-64 with naturally aligned lock-free 64-bit atomics.

C# quick start

Install the package:

dotnet add package SharedMemoryStore --version 3.0.0

Create options with the ordinary participant-aware helper:

usingSharedMemoryStore;varoptions=SharedMemoryStoreOptions.Create($"orders-{Guid.NewGuid():N}",slotCount:128,maxValueBytes:64*1024,maxDescriptorBytes:64,maxKeyBytes:64,leaseRecordCount:256,participantRecordCount:64,openMode:OpenMode.CreateNew,enableLeaseRecovery:true);StoreOpenStatusopened=MemoryStore.TryCreateOrOpen(options,outMemoryStore?store);if(opened!=StoreOpenStatus.Success||storeisnull){thrownewInvalidOperationException($"Open failed: {opened}");}using(store){byte[]key=[0x01,0x00,0x02];byte[]value=[0x10,0x00,0x20];if(store.TryPublish(key,value)!=StoreStatus.Success){thrownewInvalidOperationException("Publish failed.");}if(store.TryAcquire(key,outValueLeaselease)!=StoreStatus.Success){thrownewInvalidOperationException("Acquire failed.");}using(lease){Console.WriteLine(Convert.ToHexString(lease.ValueSpan));}StoreStatusremoved=store.TryRemove(key);if(removedis not (StoreStatus.Success or StoreStatus.RemovePending)){thrownewInvalidOperationException($"Remove failed: {removed}");}Console.WriteLine(store.ProtocolInfo);// (2, 0, 2, 7, 0)}

TryRemove makes the key logically absent at its ordering point. It returns RemovePending when a live lease or bounded cleanup still delays physical slot reuse; a later release, remove, or allocation-pressure helper may finish the reclamation.

C++ quick start

Build or install the CMake package, then consume it with:

find_package(SharedMemoryStoreCONFIGREQUIRED)
target_link_libraries(my_appPRIVATESharedMemoryStore::shared_memory_store)
#include<shared_memory_store/store.hpp>
#include<array>usingnamespaceshared_memory_store;auto options = store_options::create(
"orders", 128, 64 * 1024, 64, 64, 256, 64,
open_mode::create_or_open, true);
memory_store store;
if (memory_store::try_create_or_open(options, store) != open_status::success) {
return1;
}
const std::array<std::byte, 2> key{std::byte{1}, std::byte{2}};
const std::array<std::byte, 3> value{std::byte{7}, std::byte{8}, std::byte{9}};
if (store.try_publish(key, value) != status::success) return2;
value_lease lease;
if (store.try_acquire(key, lease) != status::success) return3;
auto borrowed = lease.value();
return lease.release() == status::success ? 0 : 4;

memory_store, value_lease, and value_reservation are move-only. Their destructors are best-effort fallbacks; explicit close, release, and abort remain the deterministic lifecycle operations.

Python quick start

Build and install the platform wheel, then use the context-managed API:

fromshared_memory_storeimportMemoryStore, OpenMode, StoreOpenStatus, StoreOptions, StoreStatusoptions=StoreOptions.create(
"orders",
slot_count=128,
max_value_bytes=64*1024,
max_descriptor_bytes=64,
max_key_bytes=64,
lease_record_count=256,
participant_record_count=64,
open_mode=OpenMode.CREATE_OR_OPEN,
enable_lease_recovery=True,
)
open_status, store=MemoryStore.open(options)
ifopen_statusisnotStoreOpenStatus.SUCCESSorstoreisNone:
raiseRuntimeError(f"open failed: {open_status}")
withstore:
ifstore.publish(b"order-1", b"payload\x00") isnotStoreStatus.SUCCESS:
raiseRuntimeError("publish failed")
acquire_status, lease=store.acquire(b"order-1")
ifacquire_statusisnotStoreStatus.SUCCESSorleaseisNone:
raiseRuntimeError(f"acquire failed: {acquire_status}")
withlease:
print(bytes(lease.value))

Python loads only the native library packaged beside its modules. A clean wheel consumer must not depend on the repository source tree or PYTHONPATH.

Waits, progress, and cancellation

Every operation accepts a no-wait, finite, or infinite policy. C# uses StoreWaitOptions, C++ uses wait_options, and Python uses WaitOptions. Finite budgets cover local retry, revalidation, helping, backoff, and any cold lifecycle wait for that call. Cancellation wins only before the operation's documented ordering point; it never rolls back an already published shared result.

StoreBusy means the call exhausted its bounded progress budget. It is a retryable contention result, not evidence of corruption and not proof that a global lock was held.

Recovery and diagnostics

Recovery is explicit and conservative. Enable it in the options, then call the lease or reservation recovery API. A record is reclaimed only when its exact participant incarnation and owner identity are safely stale. Live, changing, unsupported, or inconsistent evidence is retained and reported.

Diagnostics report the immutable five-field protocol identity plus shared capacity, slot, lease, reservation, participant, and directory facts. CAS retries, helping, contention exhaustion, invalid/stale tokens, recovery attempts, owner classifications, and status counts are local to the calling runtime or handle unless documented otherwise.

See docs/diagnostics.md for the complete distinction.

Moving an existing deployment to SMS2

There is no in-place conversion and no current client reads a noncurrent mapping to migrate it. Use application-owned authoritative data:

  1. stop publishers and prevent new readers;
  2. drain leases and reservations;
  3. close every process-local handle;
  4. remove or replace the old physical store;
  5. create a fresh SMS2 store with the intended participant-aware capacities;
  6. republish authoritative values; and
  7. start current clients.

A side-by-side cutover uses a distinct public store name. An incompatible or malformed existing mapping returns IncompatibleLayout before payload access.

Build and validation

Managed:

dotnet build SharedMemoryStore.slnx -c Release
dotnet test SharedMemoryStore.slnx -c Release
pwsh ./scripts/validate-package-consumption.ps1 -Configuration Release

Native and Python:

pwsh ./scripts/validate-native.ps1 -Configuration Release
pwsh ./scripts/validate-python.ps1 -Configuration Release

The repository also contains a deterministic protocol manifest, nine ordered runtime-pair tests, raw visibility and crash checkpoints, package-consumer tests, and Windows/Linux qualification gates.

Documentation and samples

License and project policy

SharedMemoryStore is licensed under the MIT License. See CONTRIBUTING.md, SUPPORT.md, and SECURITY.md before contributing or reporting an issue.

About

A .NET 10 shared-memory key/value store for same-host processes, with zero-copy ingest, leases, diagnostics, and runnable samples.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

SharedMemoryStore

SharedMemoryStore is a bounded, cross-process shared-memory key-value store for opaque binary keys, descriptors, and payloads. Its .NET, C++, and Python distributions implement the same lock-free SMS2 mapped protocol on Windows and Linux x64.

The store is intentionally small in scope. It publishes named values, provides zero-copy reservations and read leases, removes and reuses generations, exposes explicit recovery, and reports bounded diagnostics. Queueing, routing, subscriptions, persistence, serialization, and application schemas belong in the application layer.

Current releases and protocol

DistributionVersionRuntime surface
NuGet SharedMemoryStore3.0.0net10.0, C#
CMake SharedMemoryStore1.0.0C++20 and C ABI 2.0
Python shared-memory-store1.0.0Python 3.10+ over the packaged C ABI 2.0 library

All three create and read exactly one shared protocol:

magic=SMS2 layout=2.0 resource-protocol=2 required-features=7 optional-features=0

Package versions are independent from the mapped protocol identity. The canonical byte layout, resource names, feature masks, and distribution matrix live in protocol/README.md and protocol/compatibility.json.

Core properties

  • Fixed capacities are chosen before creation: slots, value bytes, descriptor bytes, key bytes, lease records, and participant records.
  • Every open handle owns one participant record. The default capacity is 64; exhaustion returns ParticipantTableFull without disturbing existing handles.
  • Publish, reserve, commit, acquire, release, remove, reclaim, recovery help, and diagnostics do not acquire a process-owned or store-wide OS lock.
  • Cold create, open, participant registration, close, and final resource cleanup use bounded platform coordination.
  • Keys are exact opaque byte sequences. Hashes select candidates, but equality always checks the complete key bytes.
  • Leases and reservations are generation-fenced. Their mapped views are valid only while the exact token and store handle remain alive.
  • The qualified atomic contract is little-endian x86-64 with naturally aligned lock-free 64-bit atomics.

C# quick start

Install the package:

dotnet add package SharedMemoryStore --version 3.0.0

Create options with the ordinary participant-aware helper:

usingSharedMemoryStore;varoptions=SharedMemoryStoreOptions.Create($"orders-{Guid.NewGuid():N}",slotCount:128,maxValueBytes:64*1024,maxDescriptorBytes:64,maxKeyBytes:64,leaseRecordCount:256,participantRecordCount:64,openMode:OpenMode.CreateNew,enableLeaseRecovery:true);StoreOpenStatusopened=MemoryStore.TryCreateOrOpen(options,outMemoryStore?store);if(opened!=StoreOpenStatus.Success||storeisnull){thrownewInvalidOperationException($"Open failed: {opened}");}using(store){byte[]key=[0x01,0x00,0x02];byte[]value=[0x10,0x00,0x20];if(store.TryPublish(key,value)!=StoreStatus.Success){thrownewInvalidOperationException("Publish failed.");}if(store.TryAcquire(key,outValueLeaselease)!=StoreStatus.Success){thrownewInvalidOperationException("Acquire failed.");}using(lease){Console.WriteLine(Convert.ToHexString(lease.ValueSpan));}StoreStatusremoved=store.TryRemove(key);if(removedis not (StoreStatus.Success or StoreStatus.RemovePending)){thrownewInvalidOperationException($"Remove failed: {removed}");}Console.WriteLine(store.ProtocolInfo);// (2, 0, 2, 7, 0)}

TryRemove makes the key logically absent at its ordering point. It returns RemovePending when a live lease or bounded cleanup still delays physical slot reuse; a later release, remove, or allocation-pressure helper may finish the reclamation.

C++ quick start

Build or install the CMake package, then consume it with:

find_package(SharedMemoryStoreCONFIGREQUIRED)
target_link_libraries(my_appPRIVATESharedMemoryStore::shared_memory_store)
#include<shared_memory_store/store.hpp>
#include<array>usingnamespaceshared_memory_store;auto options = store_options::create(
"orders", 128, 64 * 1024, 64, 64, 256, 64,
open_mode::create_or_open, true);
memory_store store;
if (memory_store::try_create_or_open(options, store) != open_status::success) {
return1;
}
const std::array<std::byte, 2> key{std::byte{1}, std::byte{2}};
const std::array<std::byte, 3> value{std::byte{7}, std::byte{8}, std::byte{9}};
if (store.try_publish(key, value) != status::success) return2;
value_lease lease;
if (store.try_acquire(key, lease) != status::success) return3;
auto borrowed = lease.value();
return lease.release() == status::success ? 0 : 4;

memory_store, value_lease, and value_reservation are move-only. Their destructors are best-effort fallbacks; explicit close, release, and abort remain the deterministic lifecycle operations.

Python quick start

Build and install the platform wheel, then use the context-managed API:

fromshared_memory_storeimportMemoryStore, OpenMode, StoreOpenStatus, StoreOptions, StoreStatusoptions=StoreOptions.create(
"orders",
slot_count=128,
max_value_bytes=64*1024,
max_descriptor_bytes=64,
max_key_bytes=64,
lease_record_count=256,
participant_record_count=64,
open_mode=OpenMode.CREATE_OR_OPEN,
enable_lease_recovery=True,
)
open_status, store=MemoryStore.open(options)
ifopen_statusisnotStoreOpenStatus.SUCCESSorstoreisNone:
raiseRuntimeError(f"open failed: {open_status}")
withstore:
ifstore.publish(b"order-1", b"payload\x00") isnotStoreStatus.SUCCESS:
raiseRuntimeError("publish failed")
acquire_status, lease=store.acquire(b"order-1")
ifacquire_statusisnotStoreStatus.SUCCESSorleaseisNone:
raiseRuntimeError(f"acquire failed: {acquire_status}")
withlease:
print(bytes(lease.value))

Python loads only the native library packaged beside its modules. A clean wheel consumer must not depend on the repository source tree or PYTHONPATH.

Waits, progress, and cancellation

Every operation accepts a no-wait, finite, or infinite policy. C# uses StoreWaitOptions, C++ uses wait_options, and Python uses WaitOptions. Finite budgets cover local retry, revalidation, helping, backoff, and any cold lifecycle wait for that call. Cancellation wins only before the operation's documented ordering point; it never rolls back an already published shared result.

StoreBusy means the call exhausted its bounded progress budget. It is a retryable contention result, not evidence of corruption and not proof that a global lock was held.

Recovery and diagnostics

Recovery is explicit and conservative. Enable it in the options, then call the lease or reservation recovery API. A record is reclaimed only when its exact participant incarnation and owner identity are safely stale. Live, changing, unsupported, or inconsistent evidence is retained and reported.

Diagnostics report the immutable five-field protocol identity plus shared capacity, slot, lease, reservation, participant, and directory facts. CAS retries, helping, contention exhaustion, invalid/stale tokens, recovery attempts, owner classifications, and status counts are local to the calling runtime or handle unless documented otherwise.

See docs/diagnostics.md for the complete distinction.

Moving an existing deployment to SMS2

There is no in-place conversion and no current client reads a noncurrent mapping to migrate it. Use application-owned authoritative data:

  1. stop publishers and prevent new readers;
  2. drain leases and reservations;
  3. close every process-local handle;
  4. remove or replace the old physical store;
  5. create a fresh SMS2 store with the intended participant-aware capacities;
  6. republish authoritative values; and
  7. start current clients.

A side-by-side cutover uses a distinct public store name. An incompatible or malformed existing mapping returns IncompatibleLayout before payload access.

Build and validation

Managed:

dotnet build SharedMemoryStore.slnx -c Release
dotnet test SharedMemoryStore.slnx -c Release
pwsh ./scripts/validate-package-consumption.ps1 -Configuration Release

Native and Python:

pwsh ./scripts/validate-native.ps1 -Configuration Release
pwsh ./scripts/validate-python.ps1 -Configuration Release

The repository also contains a deterministic protocol manifest, nine ordered runtime-pair tests, raw visibility and crash checkpoints, package-consumer tests, and Windows/Linux qualification gates.

Documentation and samples

License and project policy

SharedMemoryStore is licensed under the MIT License. See CONTRIBUTING.md, SUPPORT.md, and SECURITY.md before contributing or reporting an issue.

About

A .NET 10 shared-memory key/value store for same-host processes, with zero-copy ingest, leases, diagnostics, and runnable samples.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SharedMemoryStore

SharedMemoryStore is a bounded, cross-process shared-memory key-value store for opaque binary keys, descriptors, and payloads. Its .NET, C++, and Python distributions implement the same lock-free SMS2 mapped protocol on Windows and Linux x64.

The store is intentionally small in scope. It publishes named values, provides zero-copy reservations and read leases, removes and reuses generations, exposes explicit recovery, and reports bounded diagnostics. Queueing, routing, subscriptions, persistence, serialization, and application schemas belong in the application layer.

Current releases and protocol

DistributionVersionRuntime surface
NuGet SharedMemoryStore3.0.0net10.0, C#
CMake SharedMemoryStore1.0.0C++20 and C ABI 2.0
Python shared-memory-store1.0.0Python 3.10+ over the packaged C ABI 2.0 library

All three create and read exactly one shared protocol:

magic=SMS2 layout=2.0 resource-protocol=2 required-features=7 optional-features=0

Package versions are independent from the mapped protocol identity. The canonical byte layout, resource names, feature masks, and distribution matrix live in protocol/README.md and protocol/compatibility.json.

Core properties

  • Fixed capacities are chosen before creation: slots, value bytes, descriptor bytes, key bytes, lease records, and participant records.
  • Every open handle owns one participant record. The default capacity is 64; exhaustion returns ParticipantTableFull without disturbing existing handles.
  • Publish, reserve, commit, acquire, release, remove, reclaim, recovery help, and diagnostics do not acquire a process-owned or store-wide OS lock.
  • Cold create, open, participant registration, close, and final resource cleanup use bounded platform coordination.
  • Keys are exact opaque byte sequences. Hashes select candidates, but equality always checks the complete key bytes.
  • Leases and reservations are generation-fenced. Their mapped views are valid only while the exact token and store handle remain alive.
  • The qualified atomic contract is little-endian x86-64 with naturally aligned lock-free 64-bit atomics.

C# quick start

Install the package:

dotnet add package SharedMemoryStore --version 3.0.0

Create options with the ordinary participant-aware helper:

usingSharedMemoryStore;varoptions=SharedMemoryStoreOptions.Create($"orders-{Guid.NewGuid():N}",slotCount:128,maxValueBytes:64*1024,maxDescriptorBytes:64,maxKeyBytes:64,leaseRecordCount:256,participantRecordCount:64,openMode:OpenMode.CreateNew,enableLeaseRecovery:true);StoreOpenStatusopened=MemoryStore.TryCreateOrOpen(options,outMemoryStore?store);if(opened!=StoreOpenStatus.Success||storeisnull){thrownewInvalidOperationException($"Open failed: {opened}");}using(store){byte[]key=[0x01,0x00,0x02];byte[]value=[0x10,0x00,0x20];if(store.TryPublish(key,value)!=StoreStatus.Success){thrownewInvalidOperationException("Publish failed.");}if(store.TryAcquire(key,outValueLeaselease)!=StoreStatus.Success){thrownewInvalidOperationException("Acquire failed.");}using(lease){Console.WriteLine(Convert.ToHexString(lease.ValueSpan));}StoreStatusremoved=store.TryRemove(key);if(removedis not (StoreStatus.Success or StoreStatus.RemovePending)){thrownewInvalidOperationException($"Remove failed: {removed}");}Console.WriteLine(store.ProtocolInfo);// (2, 0, 2, 7, 0)}

TryRemove makes the key logically absent at its ordering point. It returns RemovePending when a live lease or bounded cleanup still delays physical slot reuse; a later release, remove, or allocation-pressure helper may finish the reclamation.

C++ quick start

Build or install the CMake package, then consume it with:

find_package(SharedMemoryStoreCONFIGREQUIRED)
target_link_libraries(my_appPRIVATESharedMemoryStore::shared_memory_store)
#include<shared_memory_store/store.hpp>
#include<array>usingnamespaceshared_memory_store;auto options = store_options::create(
"orders", 128, 64 * 1024, 64, 64, 256, 64,
open_mode::create_or_open, true);
memory_store store;
if (memory_store::try_create_or_open(options, store) != open_status::success) {
return1;
}
const std::array<std::byte, 2> key{std::byte{1}, std::byte{2}};
const std::array<std::byte, 3> value{std::byte{7}, std::byte{8}, std::byte{9}};
if (store.try_publish(key, value) != status::success) return2;
value_lease lease;
if (store.try_acquire(key, lease) != status::success) return3;
auto borrowed = lease.value();
return lease.release() == status::success ? 0 : 4;

memory_store, value_lease, and value_reservation are move-only. Their destructors are best-effort fallbacks; explicit close, release, and abort remain the deterministic lifecycle operations.

Python quick start

Build and install the platform wheel, then use the context-managed API:

fromshared_memory_storeimportMemoryStore, OpenMode, StoreOpenStatus, StoreOptions, StoreStatusoptions=StoreOptions.create(
"orders",
slot_count=128,
max_value_bytes=64*1024,
max_descriptor_bytes=64,
max_key_bytes=64,
lease_record_count=256,
participant_record_count=64,
open_mode=OpenMode.CREATE_OR_OPEN,
enable_lease_recovery=True,
)
open_status, store=MemoryStore.open(options)
ifopen_statusisnotStoreOpenStatus.SUCCESSorstoreisNone:
raiseRuntimeError(f"open failed: {open_status}")
withstore:
ifstore.publish(b"order-1", b"payload\x00") isnotStoreStatus.SUCCESS:
raiseRuntimeError("publish failed")
acquire_status, lease=store.acquire(b"order-1")
ifacquire_statusisnotStoreStatus.SUCCESSorleaseisNone:
raiseRuntimeError(f"acquire failed: {acquire_status}")
withlease:
print(bytes(lease.value))

Python loads only the native library packaged beside its modules. A clean wheel consumer must not depend on the repository source tree or PYTHONPATH.

Waits, progress, and cancellation

Every operation accepts a no-wait, finite, or infinite policy. C# uses StoreWaitOptions, C++ uses wait_options, and Python uses WaitOptions. Finite budgets cover local retry, revalidation, helping, backoff, and any cold lifecycle wait for that call. Cancellation wins only before the operation's documented ordering point; it never rolls back an already published shared result.

StoreBusy means the call exhausted its bounded progress budget. It is a retryable contention result, not evidence of corruption and not proof that a global lock was held.

Recovery and diagnostics

Recovery is explicit and conservative. Enable it in the options, then call the lease or reservation recovery API. A record is reclaimed only when its exact participant incarnation and owner identity are safely stale. Live, changing, unsupported, or inconsistent evidence is retained and reported.

Diagnostics report the immutable five-field protocol identity plus shared capacity, slot, lease, reservation, participant, and directory facts. CAS retries, helping, contention exhaustion, invalid/stale tokens, recovery attempts, owner classifications, and status counts are local to the calling runtime or handle unless documented otherwise.

See docs/diagnostics.md for the complete distinction.

Moving an existing deployment to SMS2

There is no in-place conversion and no current client reads a noncurrent mapping to migrate it. Use application-owned authoritative data:

  1. stop publishers and prevent new readers;
  2. drain leases and reservations;
  3. close every process-local handle;
  4. remove or replace the old physical store;
  5. create a fresh SMS2 store with the intended participant-aware capacities;
  6. republish authoritative values; and
  7. start current clients.

A side-by-side cutover uses a distinct public store name. An incompatible or malformed existing mapping returns IncompatibleLayout before payload access.

Build and validation

Managed:

dotnet build SharedMemoryStore.slnx -c Release
dotnet test SharedMemoryStore.slnx -c Release
pwsh ./scripts/validate-package-consumption.ps1 -Configuration Release

Native and Python:

pwsh ./scripts/validate-native.ps1 -Configuration Release
pwsh ./scripts/validate-python.ps1 -Configuration Release

The repository also contains a deterministic protocol manifest, nine ordered runtime-pair tests, raw visibility and crash checkpoints, package-consumer tests, and Windows/Linux qualification gates.

Documentation and samples

License and project policy

SharedMemoryStore is licensed under the MIT License. See CONTRIBUTING.md, SUPPORT.md, and SECURITY.md before contributing or reporting an issue.

About

A .NET 10 shared-memory key/value store for same-host processes, with zero-copy ingest, leases, diagnostics, and runnable samples.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SharedMemoryStore

SharedMemoryStore is a bounded, cross-process shared-memory key-value store for opaque binary keys, descriptors, and payloads. Its .NET, C++, and Python distributions implement the same lock-free SMS2 mapped protocol on Windows and Linux x64.

The store is intentionally small in scope. It publishes named values, provides zero-copy reservations and read leases, removes and reuses generations, exposes explicit recovery, and reports bounded diagnostics. Queueing, routing, subscriptions, persistence, serialization, and application schemas belong in the application layer.

Current releases and protocol

DistributionVersionRuntime surface
NuGet SharedMemoryStore3.0.0net10.0, C#
CMake SharedMemoryStore1.0.0C++20 and C ABI 2.0
Python shared-memory-store1.0.0Python 3.10+ over the packaged C ABI 2.0 library

All three create and read exactly one shared protocol:

magic=SMS2 layout=2.0 resource-protocol=2 required-features=7 optional-features=0

Package versions are independent from the mapped protocol identity. The canonical byte layout, resource names, feature masks, and distribution matrix live in protocol/README.md and protocol/compatibility.json.

Core properties

  • Fixed capacities are chosen before creation: slots, value bytes, descriptor bytes, key bytes, lease records, and participant records.
  • Every open handle owns one participant record. The default capacity is 64; exhaustion returns ParticipantTableFull without disturbing existing handles.
  • Publish, reserve, commit, acquire, release, remove, reclaim, recovery help, and diagnostics do not acquire a process-owned or store-wide OS lock.
  • Cold create, open, participant registration, close, and final resource cleanup use bounded platform coordination.
  • Keys are exact opaque byte sequences. Hashes select candidates, but equality always checks the complete key bytes.
  • Leases and reservations are generation-fenced. Their mapped views are valid only while the exact token and store handle remain alive.
  • The qualified atomic contract is little-endian x86-64 with naturally aligned lock-free 64-bit atomics.

C# quick start

Install the package:

dotnet add package SharedMemoryStore --version 3.0.0

Create options with the ordinary participant-aware helper:

usingSharedMemoryStore;varoptions=SharedMemoryStoreOptions.Create($"orders-{Guid.NewGuid():N}",slotCount:128,maxValueBytes:64*1024,maxDescriptorBytes:64,maxKeyBytes:64,leaseRecordCount:256,participantRecordCount:64,openMode:OpenMode.CreateNew,enableLeaseRecovery:true);StoreOpenStatusopened=MemoryStore.TryCreateOrOpen(options,outMemoryStore?store);if(opened!=StoreOpenStatus.Success||storeisnull){thrownewInvalidOperationException($"Open failed: {opened}");}using(store){byte[]key=[0x01,0x00,0x02];byte[]value=[0x10,0x00,0x20];if(store.TryPublish(key,value)!=StoreStatus.Success){thrownewInvalidOperationException("Publish failed.");}if(store.TryAcquire(key,outValueLeaselease)!=StoreStatus.Success){thrownewInvalidOperationException("Acquire failed.");}using(lease){Console.WriteLine(Convert.ToHexString(lease.ValueSpan));}StoreStatusremoved=store.TryRemove(key);if(removedis not (StoreStatus.Success or StoreStatus.RemovePending)){thrownewInvalidOperationException($"Remove failed: {removed}");}Console.WriteLine(store.ProtocolInfo);// (2, 0, 2, 7, 0)}

TryRemove makes the key logically absent at its ordering point. It returns RemovePending when a live lease or bounded cleanup still delays physical slot reuse; a later release, remove, or allocation-pressure helper may finish the reclamation.

C++ quick start

Build or install the CMake package, then consume it with:

find_package(SharedMemoryStoreCONFIGREQUIRED)
target_link_libraries(my_appPRIVATESharedMemoryStore::shared_memory_store)
#include<shared_memory_store/store.hpp>
#include<array>usingnamespaceshared_memory_store;auto options = store_options::create(
"orders", 128, 64 * 1024, 64, 64, 256, 64,
open_mode::create_or_open, true);
memory_store store;
if (memory_store::try_create_or_open(options, store) != open_status::success) {
return1;
}
const std::array<std::byte, 2> key{std::byte{1}, std::byte{2}};
const std::array<std::byte, 3> value{std::byte{7}, std::byte{8}, std::byte{9}};
if (store.try_publish(key, value) != status::success) return2;
value_lease lease;
if (store.try_acquire(key, lease) != status::success) return3;
auto borrowed = lease.value();
return lease.release() == status::success ? 0 : 4;

memory_store, value_lease, and value_reservation are move-only. Their destructors are best-effort fallbacks; explicit close, release, and abort remain the deterministic lifecycle operations.

Python quick start

Build and install the platform wheel, then use the context-managed API:

fromshared_memory_storeimportMemoryStore, OpenMode, StoreOpenStatus, StoreOptions, StoreStatusoptions=StoreOptions.create(
"orders",
slot_count=128,
max_value_bytes=64*1024,
max_descriptor_bytes=64,
max_key_bytes=64,
lease_record_count=256,
participant_record_count=64,
open_mode=OpenMode.CREATE_OR_OPEN,
enable_lease_recovery=True,
)
open_status, store=MemoryStore.open(options)
ifopen_statusisnotStoreOpenStatus.SUCCESSorstoreisNone:
raiseRuntimeError(f"open failed: {open_status}")
withstore:
ifstore.publish(b"order-1", b"payload\x00") isnotStoreStatus.SUCCESS:
raiseRuntimeError("publish failed")
acquire_status, lease=store.acquire(b"order-1")
ifacquire_statusisnotStoreStatus.SUCCESSorleaseisNone:
raiseRuntimeError(f"acquire failed: {acquire_status}")
withlease:
print(bytes(lease.value))

Python loads only the native library packaged beside its modules. A clean wheel consumer must not depend on the repository source tree or PYTHONPATH.

Waits, progress, and cancellation

Every operation accepts a no-wait, finite, or infinite policy. C# uses StoreWaitOptions, C++ uses wait_options, and Python uses WaitOptions. Finite budgets cover local retry, revalidation, helping, backoff, and any cold lifecycle wait for that call. Cancellation wins only before the operation's documented ordering point; it never rolls back an already published shared result.

StoreBusy means the call exhausted its bounded progress budget. It is a retryable contention result, not evidence of corruption and not proof that a global lock was held.

Recovery and diagnostics

Recovery is explicit and conservative. Enable it in the options, then call the lease or reservation recovery API. A record is reclaimed only when its exact participant incarnation and owner identity are safely stale. Live, changing, unsupported, or inconsistent evidence is retained and reported.

Diagnostics report the immutable five-field protocol identity plus shared capacity, slot, lease, reservation, participant, and directory facts. CAS retries, helping, contention exhaustion, invalid/stale tokens, recovery attempts, owner classifications, and status counts are local to the calling runtime or handle unless documented otherwise.

See docs/diagnostics.md for the complete distinction.

Moving an existing deployment to SMS2

There is no in-place conversion and no current client reads a noncurrent mapping to migrate it. Use application-owned authoritative data:

  1. stop publishers and prevent new readers;
  2. drain leases and reservations;
  3. close every process-local handle;
  4. remove or replace the old physical store;
  5. create a fresh SMS2 store with the intended participant-aware capacities;
  6. republish authoritative values; and
  7. start current clients.

A side-by-side cutover uses a distinct public store name. An incompatible or malformed existing mapping returns IncompatibleLayout before payload access.

Build and validation

Managed:

dotnet build SharedMemoryStore.slnx -c Release
dotnet test SharedMemoryStore.slnx -c Release
pwsh ./scripts/validate-package-consumption.ps1 -Configuration Release

Native and Python:

pwsh ./scripts/validate-native.ps1 -Configuration Release
pwsh ./scripts/validate-python.ps1 -Configuration Release

The repository also contains a deterministic protocol manifest, nine ordered runtime-pair tests, raw visibility and crash checkpoints, package-consumer tests, and Windows/Linux qualification gates.

Documentation and samples

License and project policy

SharedMemoryStore is licensed under the MIT License. See CONTRIBUTING.md, SUPPORT.md, and SECURITY.md before contributing or reporting an issue.

About

A .NET 10 shared-memory key/value store for same-host processes, with zero-copy ingest, leases, diagnostics, and runnable samples.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

SharedMemoryStore

SharedMemoryStore is a bounded, cross-process shared-memory key-value store for opaque binary keys, descriptors, and payloads. Its .NET, C++, and Python distributions implement the same lock-free SMS2 mapped protocol on Windows and Linux x64.

The store is intentionally small in scope. It publishes named values, provides zero-copy reservations and read leases, removes and reuses generations, exposes explicit recovery, and reports bounded diagnostics. Queueing, routing, subscriptions, persistence, serialization, and application schemas belong in the application layer.

Current releases and protocol

DistributionVersionRuntime surface
NuGet SharedMemoryStore3.0.0net10.0, C#
CMake SharedMemoryStore1.0.0C++20 and C ABI 2.0
Python shared-memory-store1.0.0Python 3.10+ over the packaged C ABI 2.0 library

All three create and read exactly one shared protocol:

magic=SMS2 layout=2.0 resource-protocol=2 required-features=7 optional-features=0

Package versions are independent from the mapped protocol identity. The canonical byte layout, resource names, feature masks, and distribution matrix live in protocol/README.md and protocol/compatibility.json.

Core properties

  • Fixed capacities are chosen before creation: slots, value bytes, descriptor bytes, key bytes, lease records, and participant records.
  • Every open handle owns one participant record. The default capacity is 64; exhaustion returns ParticipantTableFull without disturbing existing handles.
  • Publish, reserve, commit, acquire, release, remove, reclaim, recovery help, and diagnostics do not acquire a process-owned or store-wide OS lock.
  • Cold create, open, participant registration, close, and final resource cleanup use bounded platform coordination.
  • Keys are exact opaque byte sequences. Hashes select candidates, but equality always checks the complete key bytes.
  • Leases and reservations are generation-fenced. Their mapped views are valid only while the exact token and store handle remain alive.
  • The qualified atomic contract is little-endian x86-64 with naturally aligned lock-free 64-bit atomics.

C# quick start

Install the package:

dotnet add package SharedMemoryStore --version 3.0.0

Create options with the ordinary participant-aware helper:

usingSharedMemoryStore;varoptions=SharedMemoryStoreOptions.Create($"orders-{Guid.NewGuid():N}",slotCount:128,maxValueBytes:64*1024,maxDescriptorBytes:64,maxKeyBytes:64,leaseRecordCount:256,participantRecordCount:64,openMode:OpenMode.CreateNew,enableLeaseRecovery:true);StoreOpenStatusopened=MemoryStore.TryCreateOrOpen(options,outMemoryStore?store);if(opened!=StoreOpenStatus.Success||storeisnull){thrownewInvalidOperationException($"Open failed: {opened}");}using(store){byte[]key=[0x01,0x00,0x02];byte[]value=[0x10,0x00,0x20];if(store.TryPublish(key,value)!=StoreStatus.Success){thrownewInvalidOperationException("Publish failed.");}if(store.TryAcquire(key,outValueLeaselease)!=StoreStatus.Success){thrownewInvalidOperationException("Acquire failed.");}using(lease){Console.WriteLine(Convert.ToHexString(lease.ValueSpan));}StoreStatusremoved=store.TryRemove(key);if(removedis not (StoreStatus.Success or StoreStatus.RemovePending)){thrownewInvalidOperationException($"Remove failed: {removed}");}Console.WriteLine(store.ProtocolInfo);// (2, 0, 2, 7, 0)}

TryRemove makes the key logically absent at its ordering point. It returns RemovePending when a live lease or bounded cleanup still delays physical slot reuse; a later release, remove, or allocation-pressure helper may finish the reclamation.

C++ quick start

Build or install the CMake package, then consume it with:

find_package(SharedMemoryStoreCONFIGREQUIRED)
target_link_libraries(my_appPRIVATESharedMemoryStore::shared_memory_store)
#include<shared_memory_store/store.hpp>
#include<array>usingnamespaceshared_memory_store;auto options = store_options::create(
"orders", 128, 64 * 1024, 64, 64, 256, 64,
open_mode::create_or_open, true);
memory_store store;
if (memory_store::try_create_or_open(options, store) != open_status::success) {
return1;
}
const std::array<std::byte, 2> key{std::byte{1}, std::byte{2}};
const std::array<std::byte, 3> value{std::byte{7}, std::byte{8}, std::byte{9}};
if (store.try_publish(key, value) != status::success) return2;
value_lease lease;
if (store.try_acquire(key, lease) != status::success) return3;
auto borrowed = lease.value();
return lease.release() == status::success ? 0 : 4;

memory_store, value_lease, and value_reservation are move-only. Their destructors are best-effort fallbacks; explicit close, release, and abort remain the deterministic lifecycle operations.

Python quick start

Build and install the platform wheel, then use the context-managed API:

fromshared_memory_storeimportMemoryStore, OpenMode, StoreOpenStatus, StoreOptions, StoreStatusoptions=StoreOptions.create(
"orders",
slot_count=128,
max_value_bytes=64*1024,
max_descriptor_bytes=64,
max_key_bytes=64,
lease_record_count=256,
participant_record_count=64,
open_mode=OpenMode.CREATE_OR_OPEN,
enable_lease_recovery=True,
)
open_status, store=MemoryStore.open(options)
ifopen_statusisnotStoreOpenStatus.SUCCESSorstoreisNone:
raiseRuntimeError(f"open failed: {open_status}")
withstore:
ifstore.publish(b"order-1", b"payload\x00") isnotStoreStatus.SUCCESS:
raiseRuntimeError("publish failed")
acquire_status, lease=store.acquire(b"order-1")
ifacquire_statusisnotStoreStatus.SUCCESSorleaseisNone:
raiseRuntimeError(f"acquire failed: {acquire_status}")
withlease:
print(bytes(lease.value))

Python loads only the native library packaged beside its modules. A clean wheel consumer must not depend on the repository source tree or PYTHONPATH.

Waits, progress, and cancellation

Every operation accepts a no-wait, finite, or infinite policy. C# uses StoreWaitOptions, C++ uses wait_options, and Python uses WaitOptions. Finite budgets cover local retry, revalidation, helping, backoff, and any cold lifecycle wait for that call. Cancellation wins only before the operation's documented ordering point; it never rolls back an already published shared result.

StoreBusy means the call exhausted its bounded progress budget. It is a retryable contention result, not evidence of corruption and not proof that a global lock was held.

Recovery and diagnostics

Recovery is explicit and conservative. Enable it in the options, then call the lease or reservation recovery API. A record is reclaimed only when its exact participant incarnation and owner identity are safely stale. Live, changing, unsupported, or inconsistent evidence is retained and reported.

Diagnostics report the immutable five-field protocol identity plus shared capacity, slot, lease, reservation, participant, and directory facts. CAS retries, helping, contention exhaustion, invalid/stale tokens, recovery attempts, owner classifications, and status counts are local to the calling runtime or handle unless documented otherwise.

See docs/diagnostics.md for the complete distinction.

Moving an existing deployment to SMS2

There is no in-place conversion and no current client reads a noncurrent mapping to migrate it. Use application-owned authoritative data:

  1. stop publishers and prevent new readers;
  2. drain leases and reservations;
  3. close every process-local handle;
  4. remove or replace the old physical store;
  5. create a fresh SMS2 store with the intended participant-aware capacities;
  6. republish authoritative values; and
  7. start current clients.

A side-by-side cutover uses a distinct public store name. An incompatible or malformed existing mapping returns IncompatibleLayout before payload access.

Build and validation

Managed:

dotnet build SharedMemoryStore.slnx -c Release
dotnet test SharedMemoryStore.slnx -c Release
pwsh ./scripts/validate-package-consumption.ps1 -Configuration Release

Native and Python:

pwsh ./scripts/validate-native.ps1 -Configuration Release
pwsh ./scripts/validate-python.ps1 -Configuration Release

The repository also contains a deterministic protocol manifest, nine ordered runtime-pair tests, raw visibility and crash checkpoints, package-consumer tests, and Windows/Linux qualification gates.

Documentation and samples

License and project policy

SharedMemoryStore is licensed under the MIT License. See CONTRIBUTING.md, SUPPORT.md, and SECURITY.md before contributing or reporting an issue.

About

A .NET 10 shared-memory key/value store for same-host processes, with zero-copy ingest, leases, diagnostics, and runnable samples.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages