diff options
author | Mark Spruiell <mes@zeroc.com> | 2018-01-22 15:43:37 -0800 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2018-01-22 15:43:37 -0800 |
commit | 4b8d7ab2935d7aea3439bc679e59101a148ae460 (patch) | |
tree | 4dee838a074c865d009f0f5817e6798dc7b397ec /ruby/src | |
parent | Added missing ICEregisterIceStringConverter (diff) | |
download | ice-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.cpp | 58 |
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; |