Skip to content

Commit 2f28534

Browse files
committed
Rewrote CAtomicBoolean based on CAtomic.
1 parent 512180c commit 2f28534

File tree

5 files changed

+93
-194
lines changed

5 files changed

+93
-194
lines changed

ext/concurrent_ruby_ext/atomic_boolean.c

Lines changed: 14 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -2,82 +2,32 @@
22
#include <stdbool.h>
33

44
#include "atomic_boolean.h"
5+
#include "atomic_reference.h"
56

6-
void Check_Boolean(VALUE value) {
7-
VALUE type = TYPE(value);
8-
9-
if (type != T_TRUE && type != T_FALSE) {
10-
rb_raise(rb_eTypeError, "must be a boolean");
11-
}
7+
void atomic_boolean_mark(void *value) {
8+
rb_gc_mark_maybe((VALUE) value);
129
}
1310

14-
// http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/_005f_005fatomic-Builtins.html
15-
1611
VALUE atomic_boolean_allocate(VALUE klass) {
17-
CAtomicBoolean* atomic;
18-
VALUE sval = Data_Make_Struct(klass, CAtomicBoolean, NULL, atomic_boolean_deallocate, atomic);
19-
20-
#ifndef __USE_GCC_ATOMIC
21-
pthread_mutex_init(&atomic->mutex, NULL);
22-
#endif
23-
24-
return(sval);
25-
}
26-
27-
void atomic_boolean_deallocate(void* sval) {
28-
CAtomicBoolean* atomic = (CAtomicBoolean*) sval;
29-
30-
#ifndef __USE_GCC_ATOMIC
31-
pthread_mutex_destroy(&atomic->mutex);
32-
#endif
33-
34-
free(atomic);
12+
return rb_data_object_alloc(klass, (void *) Qfalse, atomic_boolean_mark, NULL);
3513
}
3614

3715
VALUE method_atomic_boolean_initialize(int argc, VALUE* argv, VALUE self) {
38-
CAtomicBoolean* atomic;
39-
16+
VALUE value = Qfalse;
4017
rb_check_arity(argc, 0, 1);
41-
42-
Data_Get_Struct(self, CAtomicBoolean, atomic);
43-
44-
atomic->value = (argc == 1 ? RUBY2BOOL(argv[0]) : Qfalse);
18+
if (argc == 1) value = TRUTHY(argv[0]);
19+
DATA_PTR(self) = (void *) value;
4520
return(self);
4621
}
4722

4823
VALUE method_atomic_boolean_value(VALUE self) {
49-
CAtomicBoolean* atomic;
50-
bool value;
51-
52-
Data_Get_Struct(self, CAtomicBoolean, atomic);
53-
54-
#ifdef __USE_GCC_ATOMIC
55-
value = __atomic_load_n(&atomic->value, __ATOMIC_SEQ_CST);
56-
#else
57-
pthread_mutex_lock(&atomic->mutex);
58-
value = atomic->value;
59-
pthread_mutex_unlock(&atomic->mutex);
60-
#endif
61-
62-
return BOOL2RUBY(value);
24+
return (VALUE) DATA_PTR(self);
6325
}
6426

6527
VALUE method_atomic_boolean_value_set(VALUE self, VALUE value) {
66-
CAtomicBoolean* atomic;
67-
bool new_value;
68-
69-
new_value = RUBY2BOOL(value);
70-
Data_Get_Struct(self, CAtomicBoolean, atomic);
71-
72-
#ifdef __USE_GCC_ATOMIC
73-
__atomic_store_n(&atomic->value, new_value, __ATOMIC_SEQ_CST);
74-
#else
75-
pthread_mutex_lock(&atomic->mutex);
76-
atomic->value = new_value;
77-
pthread_mutex_unlock(&atomic->mutex);
78-
#endif
79-
80-
return(value);
28+
VALUE new_value = TRUTHY(value);
29+
DATA_PTR(self) = (void *) new_value;
30+
return(new_value);
8131
}
8232

8333
VALUE method_atomic_boolean_true_question(VALUE self) {
@@ -86,53 +36,13 @@ VALUE method_atomic_boolean_true_question(VALUE self) {
8636

8737
VALUE method_atomic_boolean_false_question(VALUE self) {
8838
VALUE current = method_atomic_boolean_value(self);
89-
return(BOOL2RUBY(current == Qfalse));
39+
return(current == Qfalse ? Qtrue : Qfalse);
9040
}
9141

9242
VALUE method_atomic_boolean_make_true(VALUE self) {
93-
CAtomicBoolean* atomic;
94-
bool value = false;
95-
#ifdef __USE_GCC_ATOMIC
96-
bool expected = false;
97-
#endif
98-
99-
Data_Get_Struct(self, CAtomicBoolean, atomic);
100-
101-
#ifdef __USE_GCC_ATOMIC
102-
value = __atomic_compare_exchange_n(&atomic->value, &expected, true, false,
103-
__ATOMIC_RELEASE, __ATOMIC_SEQ_CST);
104-
#else
105-
pthread_mutex_lock(&atomic->mutex);
106-
if (! atomic->value) {
107-
atomic->value = Qtrue;
108-
value = true;
109-
}
110-
pthread_mutex_unlock(&atomic->mutex);
111-
#endif
112-
113-
return(BOOL2RUBY(value));
43+
return(ir_compare_and_set(self, Qfalse, Qtrue));
11444
}
11545

11646
VALUE method_atomic_boolean_make_false(VALUE self) {
117-
CAtomicBoolean* atomic;
118-
bool value = false;
119-
#ifdef __USE_GCC_ATOMIC
120-
bool expected = true;
121-
#endif
122-
123-
Data_Get_Struct(self, CAtomicBoolean, atomic);
124-
125-
#ifdef __USE_GCC_ATOMIC
126-
value = __atomic_compare_exchange_n(&atomic->value, &expected, false, false,
127-
__ATOMIC_RELEASE, __ATOMIC_SEQ_CST);
128-
#else
129-
pthread_mutex_lock(&atomic->mutex);
130-
if (atomic->value) {
131-
atomic->value = Qfalse;
132-
value = true;
133-
}
134-
pthread_mutex_unlock(&atomic->mutex);
135-
#endif
136-
137-
return(BOOL2RUBY(value));
47+
return(ir_compare_and_set(self, Qtrue, Qfalse));
13848
}

ext/concurrent_ruby_ext/atomic_boolean.h

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,10 @@
11
#ifndef __ATOMIC_BOOLEAN_H__
22
#define __ATOMIC_BOOLEAN_H__
33

4-
#ifdef __ATOMIC_SEQ_CST
5-
#define __USE_GCC_ATOMIC
6-
#endif
7-
8-
#ifndef __USE_GCC_ATOMIC
9-
#include <pthread.h>
10-
#endif
11-
12-
#include <stdbool.h>
13-
14-
#define RUBY2BOOL(value)(! (value == Qfalse || value == Qnil))
15-
#define BOOL2RUBY(value)(value == true ? Qtrue : Qfalse)
16-
17-
typedef struct atomic_boolean {
18-
bool value;
19-
#ifndef __USE_GCC_ATOMIC
20-
pthread_mutex_t mutex;
21-
#endif
22-
} CAtomicBoolean;
23-
24-
void Check_Boolean(VALUE);
4+
#define TRUTHY(value)(value == Qfalse || value == Qnil ? Qfalse : Qtrue)
255

6+
void atomic_boolean_mark(void*);
267
VALUE atomic_boolean_allocate(VALUE);
27-
void atomic_boolean_deallocate(void*);
288
VALUE method_atomic_boolean_initialize(int, VALUE*, VALUE);
299
VALUE method_atomic_boolean_value(VALUE);
3010
VALUE method_atomic_boolean_value_set(VALUE, VALUE);
Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,78 @@
11
#include <ruby.h>
2-
#if defined(__sun)
3-
#include <atomic.h>
4-
#endif
2+
/*#if defined(__sun)*/
3+
/*#include <atomic.h>*/
4+
/*#endif*/
55

6-
#ifdef HAVE_LIBKERN_OSATOMIC_H
7-
#include <libkern/OSAtomic.h>
8-
#endif
6+
/*#ifdef HAVE_LIBKERN_OSATOMIC_H*/
7+
/*#include <libkern/OSAtomic.h>*/
8+
/*#endif*/
99

1010
#include "atomic_reference.h"
1111

1212
void ir_mark(void *value) {
13-
rb_gc_mark_maybe((VALUE) value);
13+
rb_gc_mark_maybe((VALUE) value);
1414
}
1515

1616
VALUE ir_alloc(VALUE klass) {
17-
return rb_data_object_alloc(klass, (void *) Qnil, ir_mark, NULL);
17+
return rb_data_object_alloc(klass, (void *) Qnil, ir_mark, NULL);
1818
}
1919

2020
VALUE ir_initialize(int argc, VALUE* argv, VALUE self) {
21-
VALUE value = Qnil;
22-
if (rb_scan_args(argc, argv, "01", &value) == 1) {
23-
value = argv[0];
24-
}
25-
DATA_PTR(self) = (void *) value;
26-
return Qnil;
21+
VALUE value = Qnil;
22+
if (rb_scan_args(argc, argv, "01", &value) == 1) {
23+
value = argv[0];
24+
}
25+
DATA_PTR(self) = (void *) value;
26+
return Qnil;
2727
}
2828

2929
VALUE ir_get(VALUE self) {
30-
return (VALUE) DATA_PTR(self);
30+
return (VALUE) DATA_PTR(self);
3131
}
3232

3333
VALUE ir_set(VALUE self, VALUE new_value) {
34-
DATA_PTR(self) = (void *) new_value;
35-
return new_value;
34+
DATA_PTR(self) = (void *) new_value;
35+
return new_value;
3636
}
3737

3838
VALUE ir_get_and_set(VALUE self, VALUE new_value) {
39-
VALUE old_value;
40-
old_value = (VALUE) DATA_PTR(self);
41-
DATA_PTR(self) = (void *) new_value;
42-
return old_value;
39+
VALUE old_value;
40+
old_value = (VALUE) DATA_PTR(self);
41+
DATA_PTR(self) = (void *) new_value;
42+
return old_value;
4343
}
4444

4545
VALUE ir_compare_and_set(volatile VALUE self, VALUE expect_value, VALUE new_value) {
4646
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
47-
if (OSAtomicCompareAndSwap64(expect_value, new_value, &DATA_PTR(self))) {
48-
return Qtrue;
49-
}
47+
if (OSAtomicCompareAndSwap64(expect_value, new_value, &DATA_PTR(self))) {
48+
return Qtrue;
49+
}
5050
#elif defined(__sun)
51-
/* Assuming VALUE is uintptr_t */
52-
/* Based on the definition of uintptr_t from /usr/include/sys/int_types.h */
51+
/* Assuming VALUE is uintptr_t */
52+
/* Based on the definition of uintptr_t from /usr/include/sys/int_types.h */
5353
#if defined(_LP64) || defined(_I32LPx)
54-
/* 64-bit: uintptr_t === unsigned long */
55-
if (atomic_cas_ulong((uintptr_t *) &DATA_PTR(self), expect_value, new_value)) {
56-
return Qtrue;
57-
}
54+
/* 64-bit: uintptr_t === unsigned long */
55+
if (atomic_cas_ulong((uintptr_t *) &DATA_PTR(self), expect_value, new_value)) {
56+
return Qtrue;
57+
}
5858
#else
59-
/* 32-bit: uintptr_t === unsigned int */
60-
if (atomic_cas_uint((uintptr_t *) &DATA_PTR(self), expect_value, new_value)) {
61-
return Qtrue;
62-
}
59+
/* 32-bit: uintptr_t === unsigned int */
60+
if (atomic_cas_uint((uintptr_t *) &DATA_PTR(self), expect_value, new_value)) {
61+
return Qtrue;
62+
}
6363
#endif
6464
#elif defined _MSC_VER && defined _M_AMD64
65-
if (InterlockedCompareExchange64((LONGLONG*)&DATA_PTR(self), new_value, expect_value)) {
66-
return Qtrue;
67-
}
65+
if (InterlockedCompareExchange64((LONGLONG*)&DATA_PTR(self), new_value, expect_value)) {
66+
return Qtrue;
67+
}
6868
#elif defined _MSC_VER && defined _M_IX86
69-
if (InterlockedCompareExchange((LONG*)&DATA_PTR(self), new_value, expect_value)) {
70-
return Qtrue;
71-
}
69+
if (InterlockedCompareExchange((LONG*)&DATA_PTR(self), new_value, expect_value)) {
70+
return Qtrue;
71+
}
7272
#else
73-
if (__sync_bool_compare_and_swap(&DATA_PTR(self), expect_value, new_value)) {
74-
return Qtrue;
75-
}
73+
if (__sync_bool_compare_and_swap(&DATA_PTR(self), expect_value, new_value)) {
74+
return Qtrue;
75+
}
7676
#endif
77-
return Qfalse;
77+
return Qfalse;
7878
}

ext/concurrent_ruby_ext/atomic_reference.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
#ifndef __ATOMIC_REFERENCE_H__
22
#define __ATOMIC_REFERENCE_H__
33

4+
#if defined(__sun)
5+
#include <atomic.h>
6+
#endif
7+
8+
#ifdef HAVE_LIBKERN_OSATOMIC_H
9+
#include <libkern/OSAtomic.h>
10+
#endif
11+
412
void ir_mark(void*);
513
VALUE ir_alloc(VALUE);
614
VALUE ir_initialize(int, VALUE*, VALUE);

0 commit comments

Comments
 (0)