mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 03:07:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			61 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			61 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2020 The LevelDB-Go and Pebble Authors. All rights reserved. Use
 | 
						|
// of this source code is governed by a BSD-style license that can be found in
 | 
						|
// the LICENSE file.
 | 
						|
 | 
						|
package manual
 | 
						|
 | 
						|
// #include <stdlib.h>
 | 
						|
import "C"
 | 
						|
import "unsafe"
 | 
						|
 | 
						|
// The go:linkname directives provides backdoor access to private functions in
 | 
						|
// the runtime. Below we're accessing the throw function.
 | 
						|
 | 
						|
//go:linkname throw runtime.throw
 | 
						|
func throw(s string)
 | 
						|
 | 
						|
// TODO(peter): Rather than relying an C malloc/free, we could fork the Go
 | 
						|
// runtime page allocator and allocate large chunks of memory using mmap or
 | 
						|
// similar.
 | 
						|
 | 
						|
// New allocates a slice of size n. The returned slice is from manually managed
 | 
						|
// memory and MUST be released by calling Free. Failure to do so will result in
 | 
						|
// a memory leak.
 | 
						|
func New(n int) []byte {
 | 
						|
	if n == 0 {
 | 
						|
		return make([]byte, 0)
 | 
						|
	}
 | 
						|
	// We need to be conscious of the Cgo pointer passing rules:
 | 
						|
	//
 | 
						|
	//   https://golang.org/cmd/cgo/#hdr-Passing_pointers
 | 
						|
	//
 | 
						|
	//   ...
 | 
						|
	//   Note: the current implementation has a bug. While Go code is permitted
 | 
						|
	//   to write nil or a C pointer (but not a Go pointer) to C memory, the
 | 
						|
	//   current implementation may sometimes cause a runtime error if the
 | 
						|
	//   contents of the C memory appear to be a Go pointer. Therefore, avoid
 | 
						|
	//   passing uninitialized C memory to Go code if the Go code is going to
 | 
						|
	//   store pointer values in it. Zero out the memory in C before passing it
 | 
						|
	//   to Go.
 | 
						|
	ptr := C.calloc(C.size_t(n), 1)
 | 
						|
	if ptr == nil {
 | 
						|
		// NB: throw is like panic, except it guarantees the process will be
 | 
						|
		// terminated. The call below is exactly what the Go runtime invokes when
 | 
						|
		// it cannot allocate memory.
 | 
						|
		throw("out of memory")
 | 
						|
	}
 | 
						|
	// Interpret the C pointer as a pointer to a Go array, then slice.
 | 
						|
	return (*[MaxArrayLen]byte)(unsafe.Pointer(ptr))[:n:n]
 | 
						|
}
 | 
						|
 | 
						|
// Free frees the specified slice.
 | 
						|
func Free(b []byte) {
 | 
						|
	if cap(b) != 0 {
 | 
						|
		if len(b) == 0 {
 | 
						|
			b = b[:cap(b)]
 | 
						|
		}
 | 
						|
		ptr := unsafe.Pointer(&b[0])
 | 
						|
		C.free(ptr)
 | 
						|
	}
 | 
						|
}
 |