Skip to content

Instantly share code, notes, and snippets.

@jimsynz
Created August 7, 2017 21:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jimsynz/01bd27434681688b6670b27fe655c80d to your computer and use it in GitHub Desktop.
Save jimsynz/01bd27434681688b6670b27fe655c80d to your computer and use it in GitHub Desktop.
module Runtime
class Reference
attr_reader :object, :weight
def initialize(object, weight)
@object = object
@weight = weight
end
def self.create(object)
new(object, object.weight)
end
def clone
return split_and_clone if weight > 1
allocate_and_clone
end
def drop
object.drop_weight(weight)
end
# # rubocop:disable Style/MethodMissing
# def method_missing(*args)
# object.public_send(*args)
# end
# def respond_to_missing?(*args)
# object.public_send(*args)
# end
def ref?; true; end
private
def split_and_clone
new_weight = weight >> 1
@weight = new_weight
self.class.new(object, new_weight)
end
def allocate_and_clone
delta = object.add_weight
self.class.new(object, delta)
end
end
end
#include "src/wrc.hpp"
#include "src/hobject.hpp"
WRC::WRC(HObject *target) {
_target = target;
_target->add_weight(WRC_DEFAULT_WEIGHT);
_weight = WRC_DEFAULT_WEIGHT;
}
WRC::WRC(HObject *target, uint64_t weight) {
_target = target;
_weight = weight;
}
WRC WRC::clone() {
if (_weight > 1) {
uint64_t weight = _weight >> 1;
_weight = weight;
return WRC(_target, weight);
}
_target->add_weight(WRC_DEFAULT_WEIGHT);
return WRC(_target, WRC_DEFAULT_WEIGHT);
}
uint64_t WRC::get_weight() {
return _weight;
}
void WRC::drop() {
uint64_t tweight = _target->get_weight();
if (tweight == _weight) {
delete _target;
return;
}
_target->drop_weight(_weight);
}
HObject * WRC::operator->() {
return _target;
}
#ifndef WRC_H
#define WRC_H
#include <stdint.h>
#define WRC_DEFAULT_WEIGHT 1 << 16
class HObject;
class WRC {
private:
HObject *_target;
uint64_t _weight;
public:
WRC(HObject *target);
WRC(HObject *target, uint64_t weight);
WRC clone();
void drop();
uint64_t get_weight();
HObject * operator->();
friend inline bool operator==(const WRC lhs, const WRC rhs) {
return lhs._target == rhs._target;
};
};
#endif /* WRC_H */
use std::cell::Cell;
use std::mem;
use std::ops::Deref;
const DEFAULT_WEIGHT: u64 = 1 << 16;
#[derive(Debug)]
pub struct WRC<T> {
inner: *mut WRCInner<T>,
weight: Cell<u64>
}
#[derive(Debug)]
struct WRCInner<T> {
target: T,
weight: Cell<u64>
}
impl<T> WRC<T> {
pub fn new(target: T) -> WRC<T> {
let inner = WRCInner { target: target, weight: Cell::new(DEFAULT_WEIGHT) };
let inner = Box::into_raw(Box::new(inner));
WRC { inner: inner, weight: Cell::new(DEFAULT_WEIGHT) }
}
pub fn weight(wrc: &WRC<T>) -> u64 {
wrc.weight.get()
}
pub fn total_weight(wrc: &WRC<T>) -> u64 {
let inner = unsafe { Box::from_raw(wrc.inner) };
let total_weight = inner.weight.get();
Box::into_raw(inner);
total_weight
}
}
impl<T> Clone for WRC<T> {
fn clone(&self) -> WRC<T> {
let new_weight = self.weight.get() >> 1;
self.weight.set(new_weight);
WRC { inner: self.inner, weight: Cell::new(new_weight) }
}
}
impl<T> Drop for WRC<T> {
fn drop(&mut self) {
let weight = self.weight.get();
let inner = unsafe { Box::from_raw(self.inner) };
let total_weight = inner.weight.get();
if total_weight == weight {
mem::drop(inner);
}
else {
inner.weight.set(total_weight - weight);
self.inner = Box::into_raw(inner);
}
}
}
impl<T> Deref for WRC<T> {
type Target = T;
fn deref(&self) -> T {
// I can't figure out how to return a reference to T here with the correct lifetime.
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment