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.
Files changed (5) hide show
  1. data/README +45 -0
  2. data/ext/extconf.rb +7 -0
  3. data/ext/shlock.c +152 -0
  4. data/shlock.gemspec +17 -0
  5. 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
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+ if ( (have_library('c', 'shm_open') or
3
+ have_library('rt', 'shm_open')) and
4
+ (have_library('pthread', 'pthread_mutex_lock')) and
5
+ (have_header('pthread.h')))
6
+ create_makefile ('shlock')
7
+ end
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
+