Skip to content

Instantly share code, notes, and snippets.

@dwbuiten
Created January 30, 2016 20:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dwbuiten/bc9a3a5a69a208bd2ee8 to your computer and use it in GitHub Desktop.
Save dwbuiten/bc9a3a5a69a208bd2ee8 to your computer and use it in GitHub Desktop.
A Little CGO Abomination
// Package cref implements a way to hose your Go garbage collection.
package cref
import (
"fmt"
"unsafe"
)
/*
#include <pthread.h>
void *hold(pthread_mutex_t *mut, void *ptr)
{
pthread_mutex_lock(mut);
pthread_mutex_lock(mut);
return ptr;
}
*/
import "C"
type CRef struct {
mut C.pthread_mutex_t
}
// Ref will hold a given pointer inside a CGO call until UnRef is called.
// In Go 1.6, this should prevent Go from moving it around in memory
// and changing its address until it has been unreffed. This will, of course,
// completey hose Go's garbage collector's ability to be effective. You
// may end up with OOMs or very fragmented memory, or other wacky things.
//
// Complete untested.
func Ref(ptr unsafe.Pointer) (*CRef, error){
ret := new(CRef)
// The mutex should also not move during this time,
// allowing UnRef to work.
cret := C.pthread_mutex_init(&ret.mut, nil)
if int(cret) != 0 {
return nil, fmt.Errorf("Failed to init mutex!")
}
go C.hold(&ret.mut, ptr)
return ret, nil
}
// Allow the pointer to leave the CGO call.
func (this *CRef) UnRef() {
C.pthread_mutex_unlock(&this.mut)
C.pthread_mutex_destroy(&this.mut)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment