lazy_proxy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ff7b5afbfe188c0090183983d04cfab2d9dc926b
4
+ data.tar.gz: a363a9267dfa8d897c4cabc77f71a8de1840cb54
5
+ SHA512:
6
+ metadata.gz: afdc2c7cfc8f101c358203537566e079533898fd699d44b79c09195e09158c41f7793e518aa15a0c25e0cc906251ca621a11c30a8b1380e18c9fb45e19832834
7
+ data.tar.gz: de62f85bc27d73895b4417cc9002180b5e30e5c01dcd5ed79534c7f8f6ef01bcf9dded4adaf37979d0d558ed3de76b55e37a7ce1fa10b473392d56977440891a
data/.gitignore ADDED
@@ -0,0 +1,51 @@
1
+ *.gem
2
+ *.rbc
3
+ *.so
4
+ /.config
5
+ /coverage/
6
+ /InstalledFiles
7
+ /pkg/
8
+ /spec/reports/
9
+ /spec/examples.txt
10
+ /test/tmp/
11
+ /test/version_tmp/
12
+ /tmp/
13
+
14
+ # Used by dotenv library to load environment variables.
15
+ # .env
16
+
17
+ ## Specific to RubyMotion:
18
+ .dat*
19
+ .repl_history
20
+ build/
21
+ *.bridgesupport
22
+ build-iPhoneOS/
23
+ build-iPhoneSimulator/
24
+
25
+ ## Specific to RubyMotion (use of CocoaPods):
26
+ #
27
+ # We recommend against adding the Pods directory to your .gitignore. However
28
+ # you should judge for yourself, the pros and cons are mentioned at:
29
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
30
+ #
31
+ # vendor/Pods/
32
+
33
+ ## Documentation cache and generated files:
34
+ /.yardoc/
35
+ /_yardoc/
36
+ /doc/
37
+ /rdoc/
38
+
39
+ ## Environment normalization:
40
+ /.bundle/
41
+ /vendor/bundle
42
+ /lib/bundler/man/
43
+
44
+ # for a library or gem, you might want to ignore these files since the code is
45
+ # intended to run in multiple environments; otherwise, check them in:
46
+ # Gemfile.lock
47
+ # .ruby-version
48
+ # .ruby-gemset
49
+
50
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
51
+ .rvmrc
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ Documentation:
2
+ Enabled: false
3
+ Style/CaseEquality:
4
+ Enabled: false
5
+ Performance/StartWith:
6
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test, :development do
6
+ gem 'rspec'
7
+ gem 'rubocop'
8
+ gem 'pry'
9
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,59 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lazy_proxy (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.2.0)
10
+ coderay (1.1.1)
11
+ diff-lcs (1.2.5)
12
+ method_source (0.8.2)
13
+ parser (2.3.0.6)
14
+ ast (~> 2.2)
15
+ powerpack (0.1.1)
16
+ pry (0.10.3)
17
+ coderay (~> 1.1.0)
18
+ method_source (~> 0.8.1)
19
+ slop (~> 3.4)
20
+ rainbow (2.1.0)
21
+ rake (11.2.2)
22
+ rake-compiler (0.9.9)
23
+ rake
24
+ rspec (3.4.0)
25
+ rspec-core (~> 3.4.0)
26
+ rspec-expectations (~> 3.4.0)
27
+ rspec-mocks (~> 3.4.0)
28
+ rspec-core (3.4.4)
29
+ rspec-support (~> 3.4.0)
30
+ rspec-expectations (3.4.0)
31
+ diff-lcs (>= 1.2.0, < 2.0)
32
+ rspec-support (~> 3.4.0)
33
+ rspec-mocks (3.4.1)
34
+ diff-lcs (>= 1.2.0, < 2.0)
35
+ rspec-support (~> 3.4.0)
36
+ rspec-support (3.4.1)
37
+ rubocop (0.38.0)
38
+ parser (>= 2.3.0.6, < 3.0)
39
+ powerpack (~> 0.1)
40
+ rainbow (>= 1.99.1, < 3.0)
41
+ ruby-progressbar (~> 1.7)
42
+ unicode-display_width (~> 1.0, >= 1.0.1)
43
+ ruby-progressbar (1.7.5)
44
+ slop (3.6.0)
45
+ unicode-display_width (1.0.2)
46
+
47
+ PLATFORMS
48
+ ruby
49
+
50
+ DEPENDENCIES
51
+ lazy_proxy!
52
+ pry
53
+ rake
54
+ rake-compiler
55
+ rspec
56
+ rubocop
57
+
58
+ BUNDLED WITH
59
+ 1.12.5
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Manuel A. Valenzuela
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,9 @@
1
+ ## Efficient lazy proxy for Ruby
2
+
3
+ Can wrap any object or block returning an object.
4
+
5
+ ```ruby
6
+ LazyProxy.new(:object)
7
+ LazyProxy.new { :object }
8
+ ```
9
+ Block is only evaluated on first use.
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rake/extensiontask'
2
+ require 'rspec/core/rake_task'
3
+
4
+ spec = Gem::Specification.load('lazy_proxy.gemspec')
5
+
6
+ desc 'Check for memory leaks'
7
+ task :memory_leak_check do
8
+ require 'lazy_proxy'
9
+ top_level_threads = []
10
+ 5.times do
11
+ top_level_threads << Thread.new do
12
+ aux_class = Class.new
13
+ threads = []
14
+ 5.times do
15
+ threads << Thread.new do
16
+ loop do
17
+ 1000.times { LazyProxy.new(aux_class.new) }
18
+ GC.start
19
+ print "#{ObjectSpace.each_object(aux_class).count}\n"
20
+ end
21
+ end
22
+ end
23
+ threads.each(&:join)
24
+ end
25
+ end
26
+ top_level_threads.each(&:join)
27
+ end
28
+
29
+ task :benchmark do
30
+ require 'lazy_proxy'
31
+ require 'benchmark'
32
+
33
+ benchmark = Benchmark.measure do
34
+ 1000000.times do
35
+ LazyProxy.new(:object)
36
+ end
37
+ end.real
38
+ puts benchmark
39
+ end
40
+
41
+ desc 'Run all specs'
42
+ RSpec::Core::RakeTask.new('test') do |s|
43
+ s.rspec_opts = %w()
44
+ end
45
+
46
+ Rake::ExtensionTask.new('lazy_proxy', spec) do |ext|
47
+ ext.lib_dir = 'ext/lazy_proxy'
48
+ end
49
+
50
+ task default: [:compile, :test]
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = 'lazy_proxy'
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,167 @@
1
+ #include "lazy_proxy.h"
2
+
3
+ static void wrapped_object_mark(void *p) {
4
+ struct wrapped_object *ptr = p;
5
+ rb_gc_mark(ptr->obj);
6
+ rb_gc_mark(ptr->blk);
7
+ }
8
+
9
+ static size_t wrapped_object_memsize(const void *p) {
10
+ return sizeof(struct wrapped_object);
11
+ }
12
+
13
+ static VALUE lp_alloc(VALUE klass) {
14
+ struct wrapped_object *ptr;
15
+
16
+ return TypedData_Make_Struct(klass, struct wrapped_object, &wrapped_object_data_type, ptr);
17
+ }
18
+
19
+ static struct wrapped_object * lp_ptr(VALUE obj) {
20
+ struct wrapped_object *ptr;
21
+
22
+ TypedData_Get_Struct(obj, struct wrapped_object, &wrapped_object_data_type, ptr);
23
+ return ptr;
24
+ }
25
+
26
+ static void lp_cpy(struct wrapped_object * dst, struct wrapped_object * src) {
27
+ memcpy(dst, src, sizeof(struct wrapped_object));
28
+ }
29
+
30
+ static void lp_set(VALUE self, VALUE obj, VALUE blk, unsigned char isblk) {
31
+ struct wrapped_object data = {obj, blk, isblk, !isblk};
32
+ struct wrapped_object * ptr = lp_ptr(self);
33
+
34
+ lp_cpy(ptr, &data);
35
+ }
36
+
37
+ static void lp_resolve(struct wrapped_object * ptr) {
38
+ VALUE blk = ptr->blk, resolved = rb_funcall(blk, id_call, 0);
39
+ struct wrapped_object data = {resolved, blk, 1, 1};
40
+
41
+ lp_cpy(ptr, &data);
42
+ }
43
+
44
+ static VALUE lp_get_resolv(VALUE self) {
45
+ struct wrapped_object * ptr = lp_ptr(self);
46
+
47
+ if (lp_is_unresolved_blk(ptr))
48
+ lp_resolve(ptr);
49
+
50
+ return ptr->obj;
51
+ }
52
+
53
+ static VALUE lp_initialize(int argc, VALUE* argv, VALUE self) {
54
+ VALUE arg, blk;
55
+
56
+ rb_check_arity(argc, 0, 1);
57
+
58
+ arg = (argc == 1) ? *argv : Qnil;
59
+ blk = rb_block_given_p() ? rb_block_proc() : Qnil;
60
+
61
+ lp_set(self, arg, blk, NIL_P(arg) && !NIL_P(blk));
62
+
63
+ return self;
64
+ }
65
+
66
+ static VALUE lp_reset(VALUE self) {
67
+ struct wrapped_object * ptr = lp_ptr(self);
68
+
69
+ if(!ptr->isblk)
70
+ rb_raise(rb_eArgError, "proxy was not provided with a block");
71
+
72
+ ptr->resolved = 0;
73
+
74
+ return Qtrue;
75
+ }
76
+
77
+ static unsigned char lp_is_unresolved_blk(struct wrapped_object *ptr) {
78
+ return ptr && !ptr->resolved;
79
+ };
80
+
81
+ static VALUE lp_inspect(VALUE self) {
82
+ VALUE str, cname = rb_obj_class(self);
83
+ struct wrapped_object * ptr = lp_ptr(self);
84
+
85
+ if (lp_is_unresolved_blk(ptr))
86
+ str = rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE" (unresolved)>", rb_class_path(cname), ptr->blk);
87
+ else
88
+ str = rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE">", rb_class_path(cname), ptr->obj);
89
+
90
+ return str;
91
+ }
92
+
93
+ static VALUE lp_send(int argc, VALUE* argv, VALUE self) {
94
+ VALUE obj;
95
+ ID method_id;
96
+ rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
97
+
98
+ obj = lp_get_resolv(self);
99
+ method_id = rb_to_id(*argv);
100
+
101
+ return rb_funcall2(obj, method_id, --argc, ++argv);
102
+ }
103
+
104
+ static VALUE lp_method_missing(int argc, VALUE* argv, VALUE self) {
105
+ VALUE method_name = *argv, obj = lp_get_resolv(self);
106
+
107
+ return rb_funcallv_public(obj, SYM2ID(method_name), --argc, ++argv);
108
+ }
109
+
110
+ static VALUE lp_respond_to_missing(int argc, VALUE* argv, VALUE self) {
111
+ VALUE obj = lp_get_resolv(self);
112
+
113
+ return rb_funcall2(obj, id_respond_to, argc, argv);
114
+ }
115
+
116
+ static VALUE lp_init_copy(VALUE dst, VALUE src) {
117
+ struct wrapped_object *psrc = lp_ptr(src), *pdst;
118
+
119
+ if (!OBJ_INIT_COPY(dst, src)) return dst;
120
+
121
+ TypedData_Get_Struct(dst, struct wrapped_object, &wrapped_object_data_type, pdst);
122
+ if (!pdst)
123
+ rb_raise(rb_eArgError, "unallocated proxy");
124
+
125
+ lp_cpy(pdst, psrc);
126
+ return dst;
127
+ }
128
+
129
+ void Init_lazy_proxy() {
130
+ id_call = rb_intern("call");
131
+ id_respond_to = rb_intern("respond_to?");
132
+
133
+ rb_cLazyProxy = rb_define_class("LazyProxy", rb_cObject);
134
+
135
+ rb_define_alloc_func(rb_cLazyProxy, lp_alloc);
136
+
137
+ rb_define_method(rb_cLazyProxy, "__setobj__", lp_initialize, -1);
138
+ rb_define_method(rb_cLazyProxy, "__getobj__", lp_get_resolv, 0);
139
+ rb_define_method(rb_cLazyProxy, "__reset__", lp_reset, 0);
140
+ rb_define_method(rb_cLazyProxy, "send", lp_send, -1);
141
+ rb_define_method(rb_cLazyProxy, "inspect", lp_inspect, 0);
142
+
143
+ rb_define_private_method(rb_cLazyProxy, "initialize", lp_initialize, -1);
144
+ rb_define_private_method(rb_cLazyProxy, "initialize_copy", lp_init_copy, 1);
145
+ rb_define_private_method(rb_cLazyProxy, "method_missing", lp_method_missing, -1);
146
+ rb_define_private_method(rb_cLazyProxy, "respond_to_missing?", lp_respond_to_missing, -1);
147
+
148
+ ATTACH_FORW_FUNC("enum_for", enum_for);
149
+ ATTACH_FORW_FUNC("to_enum", to_enum);
150
+ ATTACH_FORW_FUNC("to_s", to_s);
151
+ ATTACH_FORW_FUNC("!", fnot);
152
+ ATTACH_FORW_FUNC("!=", noteql);
153
+ ATTACH_FORW_FUNC("==", eqleql);
154
+ ATTACH_FORW_FUNC("===", eqleqleql);
155
+ ATTACH_FORW_FUNC("=~", eqltld);
156
+ ATTACH_FORW_FUNC("nil?", isnil);
157
+ }
158
+
159
+ DEFINE_FORW_FUNC("enum_for", enum_for);
160
+ DEFINE_FORW_FUNC("to_enum", to_enum);
161
+ DEFINE_FORW_FUNC("to_s", to_s);
162
+ DEFINE_FORW_FUNC("!", fnot);
163
+ DEFINE_FORW_FUNC("!=", noteql);
164
+ DEFINE_FORW_FUNC("==", eqleql);
165
+ DEFINE_FORW_FUNC("===", eqleqleql);
166
+ DEFINE_FORW_FUNC("=~", eqltld);
167
+ DEFINE_FORW_FUNC("nil?", isnil);
@@ -0,0 +1,67 @@
1
+ #include <ruby.h>
2
+
3
+ #define wrapped_object_free RUBY_TYPED_DEFAULT_FREE
4
+
5
+ #define DECLARE_FORW_FUNC(method_name) \
6
+ static VALUE lp_##method_name(int argc, VALUE* argv, VALUE self);
7
+ #define DEFINE_FORW_FUNC(method_name, sanitized_name) \
8
+ static VALUE lp_##sanitized_name(int argc, VALUE* argv, VALUE self) { \
9
+ return rb_funcall2(lp_get_resolv(self), rb_intern(method_name), argc, argv); \
10
+ }
11
+ #define ATTACH_FORW_FUNC(method_name, sanitized_name) \
12
+ rb_define_method(rb_cLazyProxy, method_name, lp_##sanitized_name, -1);
13
+
14
+ static ID id_call;
15
+ static ID id_respond_to;
16
+
17
+ static VALUE rb_cLazyProxy;
18
+
19
+ struct wrapped_object {
20
+ VALUE obj;
21
+ VALUE blk;
22
+ unsigned char isblk;
23
+ unsigned char resolved;
24
+ };
25
+
26
+ static void wrapped_object_mark(void *p);
27
+ static size_t wrapped_object_memsize(const void *p);
28
+
29
+ static const rb_data_type_t wrapped_object_data_type = {
30
+ "wrapped_object",
31
+ {
32
+ wrapped_object_mark,
33
+ wrapped_object_free,
34
+ wrapped_object_memsize
35
+ },
36
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
37
+ };
38
+
39
+ static struct wrapped_object* lp_ptr(VALUE obj);
40
+ static void lp_cpy(struct wrapped_object * dst, struct wrapped_object * src);
41
+ static void lp_set(VALUE self, VALUE obj, VALUE blk, unsigned char isblk);
42
+ static void lp_resolve(struct wrapped_object * ptr);
43
+ static unsigned char lp_is_unresolved_blk(struct wrapped_object *ptr);
44
+
45
+ static VALUE lp_alloc(VALUE klass);
46
+ static VALUE lp_get_resolv(VALUE self);
47
+ static VALUE lp_initialize(int argc, VALUE* argv, VALUE self);
48
+ static VALUE lp_inspect(VALUE self);
49
+ static VALUE lp_method_missing(int argc, VALUE* argv, VALUE self);
50
+ static VALUE lp_respond_to_missing(int argc, VALUE* argv, VALUE self);
51
+ static VALUE lp_init_copy(VALUE dst, VALUE src);
52
+ static VALUE lp_send(int argc, VALUE* argv, VALUE self);
53
+
54
+ DECLARE_FORW_FUNC(enum_for);
55
+ DECLARE_FORW_FUNC(to_enum);
56
+ DECLARE_FORW_FUNC(to_s);
57
+ DECLARE_FORW_FUNC(fnot);
58
+ DECLARE_FORW_FUNC(noteql);
59
+ DECLARE_FORW_FUNC(eqleql);
60
+ DECLARE_FORW_FUNC(eqleqleql);
61
+ DECLARE_FORW_FUNC(eqltld);
62
+ DECLARE_FORW_FUNC(isnil);
63
+
64
+ void Init_lazy_proxy();
65
+
66
+
67
+
@@ -0,0 +1,24 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'lazy_proxy'
6
+ s.version = '0.0.1'
7
+ s.authors = ['Manuel A. Valenzuela']
8
+ s.email = ['manvalaco@gmail.com']
9
+
10
+ s.summary = <<-EOF
11
+ Efficient lazy object proxy
12
+ EOF
13
+ s.description = s.summary
14
+
15
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+ s.require_paths = %w(lib ext)
19
+
20
+ s.extensions << 'ext/lazy_proxy/extconf.rb'
21
+ s.add_development_dependency 'rake-compiler'
22
+ s.add_development_dependency 'rake'
23
+ s.required_ruby_version = '>= 2.0.0'
24
+ end
data/lib/lazy_proxy.rb ADDED
@@ -0,0 +1 @@
1
+ require 'lazy_proxy/lazy_proxy'
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lazy_proxy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Manuel A. Valenzuela
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Efficient lazy object proxy
42
+ email:
43
+ - manvalaco@gmail.com
44
+ executables: []
45
+ extensions:
46
+ - ext/lazy_proxy/extconf.rb
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".rubocop.yml"
51
+ - Gemfile
52
+ - Gemfile.lock
53
+ - LICENSE
54
+ - README.md
55
+ - Rakefile
56
+ - ext/lazy_proxy/extconf.rb
57
+ - ext/lazy_proxy/lazy_proxy.c
58
+ - ext/lazy_proxy/lazy_proxy.h
59
+ - lazy_proxy.gemspec
60
+ - lib/lazy_proxy.rb
61
+ homepage:
62
+ licenses: []
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ - ext
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 2.0.0
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.4.3
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Efficient lazy object proxy
85
+ test_files: []
86
+ has_rdoc: