c_buffer 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +5 -3
- data/ext/c_buffer/c_buffer.c +39 -3
- data/ext/c_buffer/c_buffer.h +10 -7
- data/ext/c_buffer/extconf.rb +3 -0
- data/rakefile.rb +4 -3
- data/test/test_c_buffer.rb +15 -11
- metadata +7 -8
- data/lib/c_buffer/c_buffer.dll +0 -0
- data/lib/c_buffer/c_buffer.so +0 -0
- data/lib/c_buffer.rb +0 -79
data/README
CHANGED
@@ -7,16 +7,18 @@
|
|
7
7
|
# author hugo benichi
|
8
8
|
# email hugo.benichi@m4x.org
|
9
9
|
# copyright 2012 hugo benichi
|
10
|
-
# version 0.1.
|
10
|
+
# version 0.1.3
|
11
11
|
#
|
12
12
|
##
|
13
13
|
|
14
14
|
installation:
|
15
15
|
|
16
|
-
run
|
16
|
+
run in the root directory
|
17
|
+
rake gem_install
|
18
|
+
|
17
19
|
it will compile the gem library and produce a .gem package for ruby
|
18
20
|
it will then install the .gem automatically
|
19
21
|
|
20
|
-
usage
|
22
|
+
usage:
|
21
23
|
|
22
24
|
cf test/test_cbuffer.rb
|
data/ext/c_buffer/c_buffer.c
CHANGED
@@ -79,7 +79,7 @@ DLL void
|
|
79
79
|
}
|
80
80
|
|
81
81
|
|
82
|
-
DLL
|
82
|
+
DLL int
|
83
83
|
cbuffer_open(
|
84
84
|
cbuffer* buf,
|
85
85
|
const char* address
|
@@ -88,8 +88,12 @@ DLL void
|
|
88
88
|
buf-> output = fopen(address, "w" );
|
89
89
|
|
90
90
|
if( !(buf->output) )
|
91
|
+
{
|
91
92
|
fprintf(stderr, "cbuffer.c: error while opening file %s\n", address);
|
92
|
-
|
93
|
+
return -1;
|
94
|
+
}
|
95
|
+
|
96
|
+
return 0;
|
93
97
|
}
|
94
98
|
|
95
99
|
|
@@ -155,7 +159,7 @@ DLL int
|
|
155
159
|
while(1)
|
156
160
|
{
|
157
161
|
fwrite( buf->outbound->mem, 1, buf-> chunk, buf-> output);
|
158
|
-
count +=
|
162
|
+
count += buf->chunk;
|
159
163
|
if( buf->stop == buf->outbound )
|
160
164
|
break;
|
161
165
|
buf->outbound = buf->outbound->next;
|
@@ -164,3 +168,35 @@ DLL int
|
|
164
168
|
fclose(buf->output);
|
165
169
|
return count;
|
166
170
|
}
|
171
|
+
|
172
|
+
|
173
|
+
DLL int
|
174
|
+
cbuffer_read(cbuffer* buf, int (*reader)(char*, void*) , void* context)
|
175
|
+
{
|
176
|
+
while( !( buf->start ) || buf->inbound == buf->start);
|
177
|
+
// busy wait while the first buffer is written
|
178
|
+
|
179
|
+
buf->outbound = buf->start;
|
180
|
+
|
181
|
+
int count = 0;
|
182
|
+
while( !( buf->stop ) )
|
183
|
+
{
|
184
|
+
reader( buf->outbound->mem, context);
|
185
|
+
|
186
|
+
count += buf->chunk;
|
187
|
+
|
188
|
+
buf->outbound = buf->outbound->next;
|
189
|
+
while(buf->outbound == buf->inbound); //busy wait
|
190
|
+
}
|
191
|
+
|
192
|
+
while(1)
|
193
|
+
{
|
194
|
+
reader( buf->outbound->mem, context);
|
195
|
+
count += buf->chunk;
|
196
|
+
if( buf->stop == buf->outbound )
|
197
|
+
break;
|
198
|
+
buf->outbound = buf->outbound->next;
|
199
|
+
}
|
200
|
+
|
201
|
+
return count;
|
202
|
+
}
|
data/ext/c_buffer/c_buffer.h
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
typedef struct cbuffer cbuffer;
|
12
12
|
typedef struct link link;
|
13
13
|
|
14
|
+
typedef int (*reader)(char*,void*);
|
14
15
|
|
15
16
|
struct
|
16
17
|
cbuffer // 192 bytes on 32bits machines and 352 bytes on 64bits machines
|
@@ -32,11 +33,13 @@ struct
|
|
32
33
|
};
|
33
34
|
|
34
35
|
|
35
|
-
DLL cbuffer* cbuffer_new (int chunk, int size);
|
36
|
-
DLL void cbuffer_free (cbuffer*);
|
37
|
-
DLL
|
36
|
+
DLL cbuffer* cbuffer_new (int chunk, int size); // size is n_chunk * chunk
|
37
|
+
DLL void cbuffer_free (cbuffer*); // don't forget to close output if open
|
38
|
+
DLL int cbuffer_open (cbuffer*, const char* ); // open a new file at the given path
|
39
|
+
|
40
|
+
DLL char* cbuffer_next (cbuffer*); // blocking, return the next buffer memory inline
|
41
|
+
DLL char* cbuffer_has_next (cbuffer*); // non-blocking, return null if not ready
|
42
|
+
DLL void cbuffer_stop (cbuffer*); // flag for stopping (cut the circular list)
|
43
|
+
DLL int cbuffer_write (cbuffer*); // blocking, write everything untill stop
|
44
|
+
DLL int cbuffer_read (cbuffer*, reader, void*); // blocking, passes memory chunk written to to a user defined handling function 'reader'
|
38
45
|
|
39
|
-
DLL char* cbuffer_next (cbuffer*); // blocking, return the next buffer memory inline
|
40
|
-
DLL char* cbuffer_has_next (cbuffer*); // non-blocking, return null if not ready
|
41
|
-
DLL void cbuffer_stop (cbuffer*); // flag for stopping (cut the circular list)
|
42
|
-
DLL int cbuffer_write (cbuffer*); // blocking, write everything untill stop
|
data/rakefile.rb
CHANGED
@@ -23,10 +23,11 @@ task :test_local do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
task :gem_install => :gem_build do
|
26
|
-
gemfile = Dir.new("./").entries.select{ |f| f =~ /
|
27
|
-
|
26
|
+
gemfile = Dir.new("./").entries.select{ |f| f =~ /c_buffer-[\d]+\.[\d]+\.[\d]+.gem/ }[0]
|
27
|
+
puts "installing %s" % gemfile
|
28
|
+
sh "gem install --local %s" % gemfile
|
28
29
|
end
|
29
30
|
|
30
|
-
task :gem_build
|
31
|
+
task :gem_build do
|
31
32
|
sh "gem build %s.gemspec" % name
|
32
33
|
end
|
data/test/test_c_buffer.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
require 'c_buffer'
|
2
2
|
|
3
|
-
repet = 126
|
3
|
+
repet = 16 #126
|
4
4
|
chunk = 1024*126
|
5
5
|
length = chunk * 64
|
6
|
+
data = Array.new(chunk){rand 255}
|
6
7
|
|
8
|
+
puts "data dump test"
|
9
|
+
CBuffer.new( path: "./data", chunk: chunk, length: length ).tap{ |buf|
|
10
|
+
buf.output
|
11
|
+
repet.times{ |i| buf.input.put_array_of_uchar 0, data }
|
12
|
+
buf.stop
|
13
|
+
}
|
7
14
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
data
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
buf.stop
|
15
|
+
puts "reader test"
|
16
|
+
CBuffer.new( chunk: chunk, length: length ).tap{ |buf|
|
17
|
+
count = 0
|
18
|
+
buf.read{ |data| puts "total data read: %i bytes" % count += data.length }
|
19
|
+
repet.times{ |i| buf.input.put_array_of_uchar 0, data }
|
20
|
+
buf.stop
|
21
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: c_buffer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
16
|
-
requirement: &
|
16
|
+
requirement: &22493360 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,19 +21,18 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *22493360
|
25
25
|
description: A simple circular buffer and its Ruby interface to go along RbScope and
|
26
26
|
RbVisa. Perfect for staging high throughput input data to low throughput I/O.
|
27
27
|
email: hugo.benichi@m4x.org
|
28
28
|
executables: []
|
29
|
-
extensions:
|
29
|
+
extensions:
|
30
|
+
- ext/c_buffer/extconf.rb
|
30
31
|
extra_rdoc_files: []
|
31
32
|
files:
|
32
|
-
- lib/c_buffer.rb
|
33
|
-
- lib/c_buffer/c_buffer.so
|
34
|
-
- lib/c_buffer/c_buffer.dll
|
35
33
|
- ext/c_buffer/c_buffer.c
|
36
34
|
- ext/c_buffer/c_buffer.h
|
35
|
+
- ext/c_buffer/extconf.rb
|
37
36
|
- rakefile.rb
|
38
37
|
- README
|
39
38
|
- test/test_c_buffer.rb
|
data/lib/c_buffer/c_buffer.dll
DELETED
Binary file
|
data/lib/c_buffer/c_buffer.so
DELETED
Binary file
|
data/lib/c_buffer.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
##
|
2
|
-
#
|
3
|
-
# CBuffer
|
4
|
-
#
|
5
|
-
# Simple circular buffer for staging data before writing to disk
|
6
|
-
#
|
7
|
-
# author hugo benichi
|
8
|
-
# email hugo.benichi@m4x.org
|
9
|
-
# copyright 2012 hugo benichi
|
10
|
-
# version 0.1.1
|
11
|
-
#
|
12
|
-
##
|
13
|
-
|
14
|
-
# Main class and namespace of the program
|
15
|
-
# This class should be instancied to use a buffer
|
16
|
-
class CBuffer
|
17
|
-
|
18
|
-
require 'ffi'
|
19
|
-
|
20
|
-
# the API module wraps the native functions of cbuffer.c
|
21
|
-
module API
|
22
|
-
extend FFI::Library
|
23
|
-
lib_type = ENV["OS"] ? "dll" : "so"
|
24
|
-
#ffi_lib $LOAD_PATH.map{ |p| p + "/cbuffer/cbuffer.#{lib_type}" }
|
25
|
-
ffi_lib File.dirname(__FILE__) + "/c_buffer/c_buffer.#{lib_type}"
|
26
|
-
[
|
27
|
-
[ :cbuffer_new, [:int32, :int32], :pointer ],
|
28
|
-
[ :cbuffer_free, [:pointer], :void ],
|
29
|
-
[ :cbuffer_open, [:pointer, :pointer], :void ],
|
30
|
-
[ :cbuffer_next, [:pointer], :pointer, :blocking => true ],
|
31
|
-
[ :cbuffer_has_next, [:pointer], :pointer ],
|
32
|
-
[ :cbuffer_stop, [:pointer], :void ],
|
33
|
-
[ :cbuffer_write, [:pointer], :int32, :blocking => true ],
|
34
|
-
].each{ |sig| attach_function *sig }
|
35
|
-
end
|
36
|
-
|
37
|
-
# the CBufferRaw class wraps the native struct memory used to store the buffer memory
|
38
|
-
# not used at the momentm here for reference only
|
39
|
-
class CBufferRaw < FFI::Struct
|
40
|
-
layout :inbound, :pointer,
|
41
|
-
:outbound, :pointer,
|
42
|
-
:start, :pointer,
|
43
|
-
:stop, :pointer,
|
44
|
-
:output, :pointer,
|
45
|
-
:chunk, :int
|
46
|
-
end
|
47
|
-
|
48
|
-
def initialize args
|
49
|
-
chunk = args[:chunk] || 1
|
50
|
-
length = args[:length] || 2
|
51
|
-
path = args[:path] || 1
|
52
|
-
@struct = API::cbuffer_new chunk, length
|
53
|
-
API::cbuffer_open @struct, path
|
54
|
-
self
|
55
|
-
end
|
56
|
-
|
57
|
-
def write &block
|
58
|
-
running = true
|
59
|
-
self.define_singleton_method :stop do
|
60
|
-
API.cbuffer_stop @struct
|
61
|
-
sleep 1 while running
|
62
|
-
API.cbuffer_free @struct
|
63
|
-
end
|
64
|
-
Thread.new do
|
65
|
-
begin
|
66
|
-
count = API.cbuffer_write @struct
|
67
|
-
running = false
|
68
|
-
block.call(count) if block
|
69
|
-
catch
|
70
|
-
puts "error in writing thread"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def next
|
76
|
-
API.cbuffer_next @struct
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|