-
Notifications
You must be signed in to change notification settings - Fork 232
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use Handle for passing foreign objects to Rust
Consolidated the various handle maps into a single implementation for each language. This handle map works basically the same as all the others, but it's API is based on the `HandleAlloc` trait. Handles have a couple properties: * All foreign handles are odd, which allows us to distinguish between Rust and foreign handles. * For handles store a map ID that can detect when a handle is used with the wrong map. Made all languages always use the handle maps for passing objects. No more trying to leak pointers from to foreign objects. Started updating the ForeignExecutor code to use handles, but this is still a WIP while the ForeignExecutor type is in it's limbo state.
- Loading branch information
Showing
52 changed files
with
388 additions
and
533 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
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,53 @@ | ||
internal class UniffiHandleMap<T> { | ||
private val lock = ReentrantReadWriteLock() | ||
private var mapId: Long = UniffiHandleMap.nextMapId() | ||
private val map: MutableMap<Long, T> = mutableMapOf() | ||
// Note: Foreign handles are always odd | ||
private var keyCounter = 1L | ||
|
||
private fun nextKey(): Long = keyCounter.also { | ||
keyCounter = (keyCounter + 2L).and(0xFFFF_FFFF_FFFFL) | ||
} | ||
|
||
private fun makeHandle(key: Long): UniffiHandle = key.or(mapId) | ||
|
||
private fun key(handle: UniffiHandle): Long { | ||
if (handle.and(0x7FFF_0000_0000_0000L) != mapId) { | ||
throw InternalException("Handle map ID mismatch") | ||
} | ||
return handle.and(0xFFFF_FFFF_FFFFL) | ||
} | ||
|
||
fun newHandle(obj: T): UniffiHandle = lock.writeLock().withLock { | ||
val key = nextKey() | ||
map[key] = obj | ||
makeHandle(key) | ||
} | ||
|
||
fun get(handle: UniffiHandle) = lock.readLock().withLock { | ||
map[key(handle)] ?: throw InternalException("Missing key in handlemap: was the handle used after being freed?") | ||
} | ||
|
||
fun cloneHandle(handle: UniffiHandle): UniffiHandle = lock.writeLock().withLock { | ||
val obj = map[key(handle)] ?: throw InternalException("Missing key in handlemap: was the handle used after being freed?") | ||
val clone = nextKey() | ||
map[clone] = obj | ||
makeHandle(clone) | ||
} | ||
|
||
fun consumeHandle(handle: UniffiHandle): T = lock.writeLock().withLock { | ||
map.remove(key(handle)) ?: throw InternalException("Missing key in handlemap: was the handle used after being freed?") | ||
} | ||
|
||
companion object { | ||
// Generate map IDs that are likely to be unique | ||
private var mapIdCounter: Long = {{ ci.namespace_hash() }}.and(0x7FFF) | ||
|
||
// Map ID, shifted into the top 16 bits | ||
internal fun nextMapId(): Long = mapIdCounter.shl(48).also { | ||
// On Kotlin, map ids are only 15 bits to get around signed/unsigned issues | ||
mapIdCounter = ((mapIdCounter + 1).and(0x7FFF)) | ||
} | ||
} | ||
} | ||
|
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
Oops, something went wrong.