summaryrefslogtreecommitdiff
path: root/ruby/src
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2018-01-22 15:43:37 -0800
committerMark Spruiell <mes@zeroc.com>2018-01-22 15:43:37 -0800
commit4b8d7ab2935d7aea3439bc679e59101a148ae460 (patch)
tree4dee838a074c865d009f0f5817e6798dc7b397ec /ruby/src
parentAdded missing ICEregisterIceStringConverter (diff)
downloadice-4b8d7ab2935d7aea3439bc679e59101a148ae460.tar.bz2
ice-4b8d7ab2935d7aea3439bc679e59101a148ae460.tar.xz
ice-4b8d7ab2935d7aea3439bc679e59101a148ae460.zip
ICE-7722 - Ice::initialize accepts a block in Ruby
Diffstat (limited to 'ruby/src')
-rw-r--r--ruby/src/IceRuby/Communicator.cpp58
1 files changed, 57 insertions, 1 deletions
diff --git a/ruby/src/IceRuby/Communicator.cpp b/ruby/src/IceRuby/Communicator.cpp
index d410b64b61c..e41a3bd9582 100644
--- a/ruby/src/IceRuby/Communicator.cpp
+++ b/ruby/src/IceRuby/Communicator.cpp
@@ -56,6 +56,27 @@ IceRuby_Communicator_free(Ice::CommunicatorPtr* p)
delete p;
}
+namespace
+{
+
+class CommunicatorDestroyer
+{
+public:
+
+ CommunicatorDestroyer(const Ice::CommunicatorPtr& c) : _communicator(c) {}
+
+ ~CommunicatorDestroyer()
+ {
+ _communicator->destroy();
+ }
+
+private:
+
+ Ice::CommunicatorPtr _communicator;
+};
+
+}
+
extern "C"
VALUE
IceRuby_initialize(int argc, VALUE* argv, VALUE self)
@@ -72,6 +93,8 @@ IceRuby_initialize(int argc, VALUE* argv, VALUE self)
// Ice::initialize(args, initData)
// Ice::initialize(args, configFile)
//
+ // An implicit block is optional.
+ //
if(argc > 2)
{
@@ -269,7 +292,40 @@ IceRuby_initialize(int argc, VALUE* argv, VALUE self)
}
_communicatorMap.insert(CommunicatorMap::value_type(communicator, reinterpret_cast<const VALUE&>(result)));
- return result;
+ //
+ // If an implicit block was provided, yield to the block and pass it the communicator instance.
+ // We destroy the communicator after the block is finished, and return the result of the block.
+ //
+ if(rb_block_given_p())
+ {
+ CommunicatorDestroyer destroyer(communicator);
+ //
+ // Examine the arity of the block procedure. If it accepts one argument, pass it the
+ // communicator. If it accepts two arguments, pass it the communicator and the
+ // argument vector.
+ //
+ VALUE proc = callRuby(rb_block_proc);
+ int arity = rb_proc_arity(proc);
+ if(arity == 1)
+ {
+ return callRuby(rb_yield, result);
+ }
+ else if(arity == 2)
+ {
+ VALUE blockArgs = createArray(2);
+ RARRAY_ASET(blockArgs, 0, result);
+ RARRAY_ASET(blockArgs, 1, args);
+ return callRuby(rb_yield, blockArgs);
+ }
+ else
+ {
+ throw RubyException(rb_eArgError, "block must accept one or two arguments");
+ }
+ }
+ else
+ {
+ return result;
+ }
}
ICE_RUBY_CATCH
return Qnil;