Skip to content

Commit a0b0177

Browse files
authored
Merge pull request #325 from Shopify/pool-raw-packer
Implement Factory::Pool #packer and #unpacker methods
2 parents 799ea5f + 3092903 commit a0b0177

12 files changed

Lines changed: 157 additions & 59 deletions

File tree

ChangeLog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
* Implement `Factory::Pool#unpacker` and `Factory::Pool#packer` to allow for more precise serialization.
12
* Require Ruby 2.5+.
23

34
2023-03-03 1.6.1:

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,33 @@ factory.register_type(
211211
factory.load(factory.dump(Point.new(12, 34))) # => #<struct Point x=12, y=34>
212212
```
213213

214+
## Pooling
215+
216+
Creating `Packer` and `Unpacker` objects is expensive. For best performance it is preferable to re-use these objects.
217+
218+
`MessagePack::Factory#pool` makes that easier:
219+
220+
```ruby
221+
factory = MessagePack::Factory.new
222+
factory.register_type(
223+
0x01,
224+
Point,
225+
packer: ->(point, packer) {
226+
packer.write(point.x)
227+
packer.write(point.y)
228+
},
229+
unpacker: ->(unpacker) {
230+
x = unpacker.read
231+
y = unpacker.read
232+
Point.new(x, y)
233+
},
234+
recursive: true,
235+
)
236+
pool = factory.pool(5) # The pool size should match the number of threads expected to use the factory concurrently.
237+
238+
pool.load(pool.dump(Point.new(12, 34))) # => #<struct Point x=12, y=34>
239+
```
240+
214241
## Buffer API
215242

216243
MessagePack for Ruby provides a buffer API so that you can read or write data by hand, not via Packer or Unpacker API.

doclib/msgpack/factory.rb

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,6 @@ class Pool
124124
# @param data [String]
125125
# @return [Object] deserialized object
126126
#
127-
# See Unpacker#initialize for supported options.
128-
#
129127
def load(data)
130128
end
131129

@@ -140,6 +138,28 @@ def load(data)
140138
#
141139
def dump(object)
142140
end
141+
142+
#
143+
# Yields an Unpacker from the pool, and check it back in.
144+
#
145+
# The unpacker should no longer be held after the block has returned.
146+
#
147+
# @yieldparam unpacker [MessagePack::Unpacker]
148+
# @returns [Object] the block return value
149+
#
150+
def unpacker(&block)
151+
end
152+
153+
#
154+
# Yields a Packer from the pool, and check it back in.
155+
#
156+
# The packer should no longer be held after the block has returned.
157+
#
158+
# @yieldparam packer [MessagePack::Packer]
159+
# @returns [Object] the block return value
160+
#
161+
def packer(&block)
162+
end
143163
end
144164
end
145165
end

doclib/msgpack/packer.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,19 @@ def size
176176
def empty?
177177
end
178178

179+
#
180+
# Returns all data in the buffer as a string, and reset the buffer.
181+
#
182+
# @return [String]
183+
#
184+
def full_pack
185+
end
186+
179187
#
180188
# Returns all data in the buffer as a string. Same as buffer.to_str.
181189
#
190+
# Does not empty the buffer, in most case _full_pack_ is prefered.
191+
#
182192
# @return [String]
183193
#
184194
def to_str

ext/java/org/msgpack/jruby/Factory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
9292
RubyHash options = null;
9393

9494
if (isFrozen()) {
95-
throw runtime.newRuntimeError("can't modify frozen Factory");
95+
throw runtime.newFrozenError("MessagePack::Factory");
9696
}
9797

9898
if (args.length == 2) {

ext/java/org/msgpack/jruby/Packer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ public IRubyObject registeredTypesInternal(ThreadContext ctx) {
9696
@JRubyMethod(name = "register_type", required = 2, optional = 1)
9797
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
9898
Ruby runtime = ctx.runtime;
99+
if (isFrozen()) {
100+
throw runtime.newFrozenError("MessagePack::Packer");
101+
}
99102
IRubyObject type = args[0];
100103
IRubyObject mod = args[1];
101104

ext/java/org/msgpack/jruby/Unpacker.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ public IRubyObject registeredTypesInternal(ThreadContext ctx) {
130130
@JRubyMethod(name = "register_type", required = 1, optional = 2)
131131
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
132132
Ruby runtime = ctx.runtime;
133+
if (isFrozen()) {
134+
throw runtime.newFrozenError("MessagePack::Unpacker");
135+
}
133136
IRubyObject type = args[0];
134137

135138
RubyModule extModule;

ext/msgpack/factory_class.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
212212
VALUE packer_proc, unpacker_proc;
213213

214214
if (OBJ_FROZEN(self)) {
215-
rb_raise(rb_eRuntimeError, "can't modify frozen Factory");
215+
rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
216216
}
217217

218218
switch (argc) {

ext/msgpack/packer_class.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ static VALUE Packer_registered_types_internal(VALUE self)
349349

350350
static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
351351
{
352+
if (OBJ_FROZEN(self)) {
353+
rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Packer");
354+
}
355+
352356
msgpack_packer_t *pk = MessagePack_Packer_get(self);
353357

354358
int ext_type;

ext/msgpack/unpacker_class.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ static VALUE Unpacker_registered_types_internal(VALUE self)
348348

349349
static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
350350
{
351+
if (OBJ_FROZEN(self)) {
352+
rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Unpacker");
353+
}
354+
351355
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
352356

353357
int ext_type;
@@ -446,7 +450,7 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
446450
rb_define_method(cMessagePack_Unpacker, "read_array_header", Unpacker_read_array_header, 0);
447451
rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
448452
rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed_reference, 1);
449-
rb_define_method(cMessagePack_Unpacker, "feed_reference", Unpacker_feed_reference, 1);
453+
rb_define_alias(cMessagePack_Unpacker, "feed_reference", "feed");
450454
rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);
451455
rb_define_method(cMessagePack_Unpacker, "feed_each", Unpacker_feed_each, 1);
452456
rb_define_method(cMessagePack_Unpacker, "reset", Unpacker_reset, 0);

0 commit comments

Comments
 (0)