ice799-shlock 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +45 -0
- data/ext/extconf.rb +7 -0
- data/ext/shlock.c +152 -0
- data/shlock.gemspec +17 -0
- metadata +57 -0
data/README
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
What is putex ?
|
2
|
+
===============
|
3
|
+
|
4
|
+
putex is an interproces mutex that uses shared memory (PUTEX = Process mUTEX).
|
5
|
+
|
6
|
+
|
7
|
+
Why ?
|
8
|
+
=====
|
9
|
+
|
10
|
+
If want to synchronize two ruby processes without using those painful file locks, you can use this.
|
11
|
+
|
12
|
+
|
13
|
+
Sample Usage:
|
14
|
+
=============
|
15
|
+
|
16
|
+
process1.rb:
|
17
|
+
require 'putex'
|
18
|
+
f = Putex.new("/test-mutex")
|
19
|
+
f.lock
|
20
|
+
puts("locked the mutex once, grabbing lock again to spin-wait; go run process2.rb once locked up...\n")
|
21
|
+
f.lock
|
22
|
+
puts("got the lock, exiting\n")
|
23
|
+
|
24
|
+
|
25
|
+
process2.rb:
|
26
|
+
require 'putex'
|
27
|
+
f = Putex.new("/text-mutex")
|
28
|
+
puts "alive, unlocking"
|
29
|
+
f.unlock
|
30
|
+
puts "done, exiting"
|
31
|
+
f.destroy
|
32
|
+
|
33
|
+
|
34
|
+
in your terminal:
|
35
|
+
% ruby process1.rb
|
36
|
+
|
37
|
+
when it tells you to run process2.rb, in another terminal enter:
|
38
|
+
% ruby process2.rb
|
39
|
+
|
40
|
+
you should see process2 unlock process1 and allow it to exit.
|
41
|
+
|
42
|
+
What's next ?
|
43
|
+
=============
|
44
|
+
|
45
|
+
Maybe some more process-to-process synchronization primitives?
|
data/ext/extconf.rb
ADDED
data/ext/shlock.c
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
#define _GNU_SOURCE
|
2
|
+
#include "ruby.h"
|
3
|
+
#include <sys/types.h>
|
4
|
+
#include <pthread.h>
|
5
|
+
#include <sys/mman.h>
|
6
|
+
#include <fcntl.h>
|
7
|
+
#include <errno.h>
|
8
|
+
#include <sys/stat.h>
|
9
|
+
|
10
|
+
struct mutex_info {
|
11
|
+
pthread_mutex_t m;
|
12
|
+
int fd;
|
13
|
+
};
|
14
|
+
|
15
|
+
struct rwlock_info {
|
16
|
+
pthread_rwlock_t rwlock;
|
17
|
+
int fd;
|
18
|
+
};
|
19
|
+
|
20
|
+
static int shared_mem_open(const char *name) {
|
21
|
+
int fd = shm_open (name, O_RDWR, S_IRUSR | S_IWUSR);
|
22
|
+
if (fd < 0) {
|
23
|
+
fd = shm_open (name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
24
|
+
if (ftruncate(fd, sizeof(struct mutex_info)) == -1) {
|
25
|
+
printf("ftruncate error: %s\n", strerror(errno));
|
26
|
+
return -1;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
if (fd < 0) {
|
31
|
+
printf("error: %s\n", strerror(errno));
|
32
|
+
return -1;
|
33
|
+
}
|
34
|
+
|
35
|
+
return fd;
|
36
|
+
}
|
37
|
+
|
38
|
+
static VALUE rb_putex_new (VALUE self, VALUE name) {
|
39
|
+
struct mutex_info *ms;
|
40
|
+
int fd = shared_mem_open(StringValuePtr(name));
|
41
|
+
if (fd < 0)
|
42
|
+
return Qnil;
|
43
|
+
|
44
|
+
ms = (struct mutex_info *)mmap(NULL, sizeof(struct mutex_info), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
45
|
+
if (ms == MAP_FAILED) {
|
46
|
+
printf("mmap error: %s\n", strerror(errno));
|
47
|
+
return Qnil;
|
48
|
+
}
|
49
|
+
ms->fd = fd;
|
50
|
+
fsync(fd);
|
51
|
+
VALUE obj = Data_Wrap_Struct(self, NULL, NULL, ms);
|
52
|
+
return obj;
|
53
|
+
}
|
54
|
+
|
55
|
+
static VALUE rb_putex_destroy (VALUE self) {
|
56
|
+
struct mutex_info *m;
|
57
|
+
Data_Get_Struct(self, struct mutex_info, m);
|
58
|
+
fsync(m->fd);
|
59
|
+
close(m->fd);
|
60
|
+
|
61
|
+
return Qnil;
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE rb_putex_lock (VALUE self) {
|
65
|
+
struct mutex_info *fs;
|
66
|
+
Data_Get_Struct(self, struct mutex_info, fs);
|
67
|
+
pthread_mutex_lock(&(fs->m));
|
68
|
+
|
69
|
+
return Qnil;
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE rb_putex_unlock (VALUE self) {
|
73
|
+
struct mutex_info *fs;
|
74
|
+
Data_Get_Struct(self, struct mutex_info, fs);
|
75
|
+
pthread_mutex_unlock(&(fs->m));
|
76
|
+
|
77
|
+
return Qnil;
|
78
|
+
}
|
79
|
+
|
80
|
+
static VALUE rb_rwlock_new (VALUE self, VALUE name) {
|
81
|
+
struct rwlock_info *rws;
|
82
|
+
int fd = shared_mem_open (StringValuePtr(name));
|
83
|
+
if (fd < 0)
|
84
|
+
return Qnil;
|
85
|
+
|
86
|
+
rws = (struct rwlock_info *)mmap(NULL, sizeof(struct rwlock_info), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
87
|
+
if (rws == MAP_FAILED) {
|
88
|
+
printf("mmap error: %s\n", strerror(errno));
|
89
|
+
return Qnil;
|
90
|
+
}
|
91
|
+
rws->fd = fd;
|
92
|
+
fsync(fd);
|
93
|
+
|
94
|
+
VALUE obj = Data_Wrap_Struct(self, NULL, NULL, rws);
|
95
|
+
return obj;
|
96
|
+
}
|
97
|
+
|
98
|
+
static VALUE rb_rwlock_destory (VALUE self) {
|
99
|
+
struct rwlock_info *rws;
|
100
|
+
Data_Get_Struct(self, struct rwlock_info, rws);
|
101
|
+
fsync(rws->fd);
|
102
|
+
close(rws->fd);
|
103
|
+
|
104
|
+
return Qnil;
|
105
|
+
}
|
106
|
+
|
107
|
+
static VALUE rb_rwlock_read_lock (VALUE self) {
|
108
|
+
struct rwlock_info *rws;
|
109
|
+
Data_Get_Struct(self, struct rwlock_info, rws);
|
110
|
+
pthread_rwlock_rdlock(&(rws->rwlock));
|
111
|
+
|
112
|
+
return Qnil;
|
113
|
+
}
|
114
|
+
|
115
|
+
static VALUE rb_rwlock_write_lock (VALUE self) {
|
116
|
+
struct rwlock_info *rws;
|
117
|
+
Data_Get_Struct (self, struct rwlock_info, rws);
|
118
|
+
pthread_rwlock_wrlock(&(rws->rwlock));
|
119
|
+
|
120
|
+
return Qnil;
|
121
|
+
}
|
122
|
+
|
123
|
+
static VALUE rb_rwlock_unlock (VALUE self) {
|
124
|
+
struct rwlock_info *rws;
|
125
|
+
Data_Get_Struct (self, struct rwlock_info, rws);
|
126
|
+
int e = pthread_rwlock_unlock(&(rws->rwlock));
|
127
|
+
|
128
|
+
if (e != 0) {
|
129
|
+
printf("error: %d\n", e);
|
130
|
+
}
|
131
|
+
return Qnil;
|
132
|
+
}
|
133
|
+
|
134
|
+
void Init_shlock() {
|
135
|
+
VALUE shared_lock_module = rb_define_module("Shlock");
|
136
|
+
|
137
|
+
/* Shlock::Putex */
|
138
|
+
|
139
|
+
VALUE putex_class = rb_define_class_under(shared_lock_module, "Putex", rb_cObject);
|
140
|
+
rb_define_singleton_method(putex_class, "new", rb_putex_new, 1);
|
141
|
+
rb_define_method(putex_class, "lock", rb_putex_lock, 0);
|
142
|
+
rb_define_method(putex_class, "unlock", rb_putex_unlock, 0);
|
143
|
+
rb_define_method(putex_class, "destroy", rb_putex_destroy, 0);
|
144
|
+
|
145
|
+
/* Shlock::Prwlock */
|
146
|
+
|
147
|
+
VALUE prwlock_class = rb_define_class_under(shared_lock_module, "Prwlock", rb_cObject);
|
148
|
+
rb_define_singleton_method(prwlock_class, "new", rb_rwlock_new, 1);
|
149
|
+
rb_define_method(prwlock_class, "read_lock", rb_rwlock_read_lock, 0);
|
150
|
+
rb_define_method(prwlock_class, "write_lock", rb_rwlock_write_lock, 0);
|
151
|
+
rb_define_method(prwlock_class, "unlock", rb_rwlock_unlock, 0);
|
152
|
+
}
|
data/shlock.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
spec = Gem::Specification.new do |s|
|
2
|
+
s.name = 'shlock'
|
3
|
+
s.version = '0.0.2'
|
4
|
+
s.date = '2009-03-20'
|
5
|
+
s.summary = 'Inter-process synchronization primitives using shared memory'
|
6
|
+
s.email = "ice799@gmail.com"
|
7
|
+
s.homepage = "http://github.com/ice799/putex/tree/master"
|
8
|
+
s.description = "inter-process synchronization primitives using shared memory"
|
9
|
+
s.has_rdoc = false
|
10
|
+
s.authors = ["Joe Damato"]
|
11
|
+
s.extensions = "ext/extconf.rb"
|
12
|
+
s.require_paths << "ext"
|
13
|
+
s.files = ["README",
|
14
|
+
"shlock.gemspec",
|
15
|
+
"ext/shlock.c",
|
16
|
+
"ext/extconf.rb"]
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ice799-shlock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joe Damato
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-20 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: inter-process synchronization primitives using shared memory
|
17
|
+
email: ice799@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions:
|
21
|
+
- ext/extconf.rb
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- shlock.gemspec
|
27
|
+
- ext/shlock.c
|
28
|
+
- ext/extconf.rb
|
29
|
+
has_rdoc: false
|
30
|
+
homepage: http://github.com/ice799/putex/tree/master
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
- ext
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: "0"
|
42
|
+
version:
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
requirements: []
|
50
|
+
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.2.0
|
53
|
+
signing_key:
|
54
|
+
specification_version: 2
|
55
|
+
summary: Inter-process synchronization primitives using shared memory
|
56
|
+
test_files: []
|
57
|
+
|