Created
August 7, 2017 21:57
-
-
Save jimsynz/01bd27434681688b6670b27fe655c80d to your computer and use it in GitHub Desktop.
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
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 |
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
#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; | |
} |
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
#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 */ |
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
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