Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 37 additions & 24 deletions ext/concurrent-ruby-ext/atomic_boolean.c
Original file line number Diff line number Diff line change
@@ -1,54 +1,67 @@
#include <ruby.h>

#include "atomic_boolean.h"
#include "atomic_reference.h"

void atomic_boolean_mark(void *value) {
rb_gc_mark_maybe((VALUE) value);
}

const rb_data_type_t atomic_boolean_type = {
"Concurrent::CAtomicBoolean",
{
atomic_boolean_mark,
RUBY_NEVER_FREE,
},
};
CR_DEFINE_ATOMIC_DATA_TYPE(atomic_boolean_type, "Concurrent::CAtomicBoolean");

VALUE atomic_boolean_allocate(VALUE klass) {
return rb_data_typed_object_wrap(klass, (void *) Qfalse, &atomic_boolean_type);
cr_atomic_t *atomic;
VALUE obj = TypedData_Make_Struct(klass, cr_atomic_t, &atomic_boolean_type, atomic);
RB_OBJ_WRITE(obj, &atomic->value, Qfalse);
return obj;
}

VALUE method_atomic_boolean_initialize(int argc, VALUE* argv, VALUE self) {
VALUE method_atomic_boolean_initialize(int argc, VALUE *argv, VALUE self) {
cr_atomic_t *atomic;
VALUE value = Qfalse;
TypedData_Get_Struct(self, cr_atomic_t, &atomic_boolean_type, atomic);

rb_check_arity(argc, 0, 1);
if (argc == 1) value = TRUTHY(argv[0]);
DATA_PTR(self) = (void *) value;
return(self);
RB_OBJ_WRITE(self, &atomic->value, value);
return self;
}

VALUE method_atomic_boolean_value(VALUE self) {
return(ir_get(self));
cr_atomic_t *atomic;
TypedData_Get_Struct(self, cr_atomic_t, &atomic_boolean_type, atomic);
return cr_atomic_value_load(atomic);
}

VALUE method_atomic_boolean_value_set(VALUE self, VALUE value) {
cr_atomic_t *atomic;
VALUE new_value = TRUTHY(value);
return(ir_set(self, new_value));
TypedData_Get_Struct(self, cr_atomic_t, &atomic_boolean_type, atomic);
cr_atomic_value_set(atomic, new_value);
RB_OBJ_WRITTEN(self, Qundef, new_value);
return new_value;
}

VALUE method_atomic_boolean_true_question(VALUE self) {
return(method_atomic_boolean_value(self));
return method_atomic_boolean_value(self);
}

VALUE method_atomic_boolean_false_question(VALUE self) {
VALUE current = method_atomic_boolean_value(self);
return(current == Qfalse ? Qtrue : Qfalse);
return method_atomic_boolean_value(self) == Qfalse ? Qtrue : Qfalse;
}

VALUE method_atomic_boolean_make_true(VALUE self) {
return(ir_compare_and_set(self, Qfalse, Qtrue));
cr_atomic_t *atomic;
TypedData_Get_Struct(self, cr_atomic_t, &atomic_boolean_type, atomic);

if (cr_atomic_value_cas(atomic, Qfalse, Qtrue) == Qfalse) {
RB_OBJ_WRITTEN(self, Qfalse, Qtrue);
return Qtrue;
}
return Qfalse;
}

VALUE method_atomic_boolean_make_false(VALUE self) {
return(ir_compare_and_set(self, Qtrue, Qfalse));
cr_atomic_t *atomic;
TypedData_Get_Struct(self, cr_atomic_t, &atomic_boolean_type, atomic);

if (cr_atomic_value_cas(atomic, Qtrue, Qfalse) == Qtrue) {
RB_OBJ_WRITTEN(self, Qtrue, Qfalse);
return Qtrue;
}
return Qfalse;
}
25 changes: 13 additions & 12 deletions ext/concurrent-ruby-ext/atomic_boolean.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#ifndef __ATOMIC_BOOLEAN_H__
#define __ATOMIC_BOOLEAN_H__
#ifndef CONCURRENT_RUBY_ATOMIC_BOOLEAN_H
#define CONCURRENT_RUBY_ATOMIC_BOOLEAN_H 1

#define TRUTHY(value)(value == Qfalse || value == Qnil ? Qfalse : Qtrue)
#include <ruby.h>

void atomic_boolean_mark(void*);
VALUE atomic_boolean_allocate(VALUE);
VALUE method_atomic_boolean_initialize(int, VALUE*, VALUE);
VALUE method_atomic_boolean_value(VALUE);
VALUE method_atomic_boolean_value_set(VALUE, VALUE);
VALUE method_atomic_boolean_true_question(VALUE);
VALUE method_atomic_boolean_false_question(VALUE);
VALUE method_atomic_boolean_make_true(VALUE);
VALUE method_atomic_boolean_make_false(VALUE);
#define TRUTHY(value) (((value) == Qfalse || (value) == Qnil) ? Qfalse : Qtrue)

VALUE atomic_boolean_allocate(VALUE klass);
VALUE method_atomic_boolean_initialize(int argc, VALUE *argv, VALUE self);
VALUE method_atomic_boolean_value(VALUE self);
VALUE method_atomic_boolean_value_set(VALUE self, VALUE value);
VALUE method_atomic_boolean_true_question(VALUE self);
VALUE method_atomic_boolean_false_question(VALUE self);
VALUE method_atomic_boolean_make_true(VALUE self);
VALUE method_atomic_boolean_make_false(VALUE self);

#endif
86 changes: 54 additions & 32 deletions ext/concurrent-ruby-ext/atomic_fixnum.c
Original file line number Diff line number Diff line change
@@ -1,79 +1,101 @@
#include <ruby.h>

#include "atomic_fixnum.h"
#include "atomic_reference.h"

void atomic_fixnum_mark(void *value) {
rb_gc_mark_maybe((VALUE) value);
}

const rb_data_type_t atomic_fixnum_type = {
"Concurrent::CAtomicFixnum",
{
atomic_fixnum_mark,
RUBY_NEVER_FREE,
},
};
CR_DEFINE_ATOMIC_DATA_TYPE(atomic_fixnum_type, "Concurrent::CAtomicFixnum");

VALUE atomic_fixnum_allocate(VALUE klass) {
return rb_data_typed_object_wrap(klass, (void *) Qnil, &atomic_fixnum_type);
cr_atomic_t *atomic;
VALUE obj = TypedData_Make_Struct(klass, cr_atomic_t, &atomic_fixnum_type, atomic);
RB_OBJ_WRITE(obj, &atomic->value, Qnil);
return obj;
}

VALUE method_atomic_fixnum_initialize(int argc, VALUE* argv, VALUE self) {
VALUE method_atomic_fixnum_initialize(int argc, VALUE *argv, VALUE self) {
cr_atomic_t *atomic;
VALUE value = LL2NUM(0);
TypedData_Get_Struct(self, cr_atomic_t, &atomic_fixnum_type, atomic);

rb_check_arity(argc, 0, 1);
if (argc == 1) {
Check_Type(argv[0], T_FIXNUM);
value = argv[0];
}
DATA_PTR(self) = (void *) value;
return(self);
RB_OBJ_WRITE(self, &atomic->value, value);
return self;
}

VALUE method_atomic_fixnum_value(VALUE self) {
return (VALUE) DATA_PTR(self);
cr_atomic_t *atomic;
TypedData_Get_Struct(self, cr_atomic_t, &atomic_fixnum_type, atomic);
return cr_atomic_value_load(atomic);
}

VALUE method_atomic_fixnum_value_set(VALUE self, VALUE value) {
cr_atomic_t *atomic;
Check_Type(value, T_FIXNUM);
DATA_PTR(self) = (void *) value;
return(value);
TypedData_Get_Struct(self, cr_atomic_t, &atomic_fixnum_type, atomic);
cr_atomic_value_set(atomic, value);
RB_OBJ_WRITTEN(self, Qundef, value);
return value;
}

VALUE method_atomic_fixnum_increment(int argc, VALUE* argv, VALUE self) {
long long value = NUM2LL((VALUE) DATA_PTR(self));
VALUE method_atomic_fixnum_increment(int argc, VALUE *argv, VALUE self) {
cr_atomic_t *atomic;
long long delta = 1;
VALUE new_value;
TypedData_Get_Struct(self, cr_atomic_t, &atomic_fixnum_type, atomic);

rb_check_arity(argc, 0, 1);
if (argc == 1) {
Check_Type(argv[0], T_FIXNUM);
delta = NUM2LL(argv[0]);
}
return method_atomic_fixnum_value_set(self, LL2NUM(value + delta));
new_value = LL2NUM(NUM2LL(cr_atomic_value_load(atomic)) + delta);
cr_atomic_value_set(atomic, new_value);
RB_OBJ_WRITTEN(self, Qundef, new_value);
return new_value;
}

VALUE method_atomic_fixnum_decrement(int argc, VALUE* argv, VALUE self) {
long long value = NUM2LL((VALUE) DATA_PTR(self));
VALUE method_atomic_fixnum_decrement(int argc, VALUE *argv, VALUE self) {
cr_atomic_t *atomic;
long long delta = 1;
VALUE new_value;
TypedData_Get_Struct(self, cr_atomic_t, &atomic_fixnum_type, atomic);

rb_check_arity(argc, 0, 1);
if (argc == 1) {
Check_Type(argv[0], T_FIXNUM);
delta = NUM2LL(argv[0]);
}
return method_atomic_fixnum_value_set(self, LL2NUM(value - delta));
new_value = LL2NUM(NUM2LL(cr_atomic_value_load(atomic)) - delta);
cr_atomic_value_set(atomic, new_value);
RB_OBJ_WRITTEN(self, Qundef, new_value);
return new_value;
}

VALUE method_atomic_fixnum_compare_and_set(VALUE self, VALUE rb_expect, VALUE rb_update) {
Check_Type(rb_expect, T_FIXNUM);
Check_Type(rb_update, T_FIXNUM);
return ir_compare_and_set(self, rb_expect, rb_update);
VALUE method_atomic_fixnum_compare_and_set(VALUE self, VALUE expect, VALUE update) {
cr_atomic_t *atomic;
Check_Type(expect, T_FIXNUM);
Check_Type(update, T_FIXNUM);
TypedData_Get_Struct(self, cr_atomic_t, &atomic_fixnum_type, atomic);

if (cr_atomic_value_cas(atomic, expect, update) == expect) {
RB_OBJ_WRITTEN(self, expect, update);
return Qtrue;
}
return Qfalse;
}

VALUE method_atomic_fixnum_update(VALUE self) {
cr_atomic_t *atomic;
VALUE old_value, new_value;
TypedData_Get_Struct(self, cr_atomic_t, &atomic_fixnum_type, atomic);

for (;;) {
old_value = method_atomic_fixnum_value(self);
old_value = cr_atomic_value_load(atomic);
new_value = rb_yield(old_value);
if (ir_compare_and_set(self, old_value, new_value) == Qtrue) {
if (cr_atomic_value_cas(atomic, old_value, new_value) == old_value) {
RB_OBJ_WRITTEN(self, old_value, new_value);
return new_value;
}
}
Expand Down
23 changes: 12 additions & 11 deletions ext/concurrent-ruby-ext/atomic_fixnum.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#ifndef __ATOMIC_FIXNUM_H__
#define __ATOMIC_FIXNUM_H__
#ifndef CONCURRENT_RUBY_ATOMIC_FIXNUM_H
#define CONCURRENT_RUBY_ATOMIC_FIXNUM_H 1

void atomic_fixnum_mark(void*);
VALUE atomic_fixnum_allocate(VALUE);
VALUE method_atomic_fixnum_initialize(int, VALUE*, VALUE);
VALUE method_atomic_fixnum_value(VALUE);
VALUE method_atomic_fixnum_value_set(VALUE, VALUE);
VALUE method_atomic_fixnum_increment(int, VALUE*, VALUE);
VALUE method_atomic_fixnum_decrement(int, VALUE*, VALUE);
VALUE method_atomic_fixnum_compare_and_set(VALUE, VALUE, VALUE);
VALUE method_atomic_fixnum_update(VALUE);
#include <ruby.h>

VALUE atomic_fixnum_allocate(VALUE klass);
VALUE method_atomic_fixnum_initialize(int argc, VALUE *argv, VALUE self);
VALUE method_atomic_fixnum_value(VALUE self);
VALUE method_atomic_fixnum_value_set(VALUE self, VALUE value);
VALUE method_atomic_fixnum_increment(int argc, VALUE *argv, VALUE self);
VALUE method_atomic_fixnum_decrement(int argc, VALUE *argv, VALUE self);
VALUE method_atomic_fixnum_compare_and_set(VALUE self, VALUE expect, VALUE update);
VALUE method_atomic_fixnum_update(VALUE self);

#endif
Loading