aboutsummaryrefslogtreecommitdiffstats
path: root/ext/socket/lib
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-17 00:58:23 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-17 00:58:23 +0000
commit790a45f98f2e8de61e261588b07348e668ce9464 (patch)
tree0dc76a795840b9f9e299c6f086fdaae7d6fe36e3 /ext/socket/lib
parentf335eab8c71614d764e4ce499ea82e1046b50db4 (diff)
downloadruby-790a45f98f2e8de61e261588b07348e668ce9464.tar.gz
socket (bsock_recvmsg_internal): avoid arg parsing
* ext/socket/ancdata.c (bsock_recvmsg_internal): avoid arg parsing (rsock_bsock_recvmsg): adjust for above change (rsock_bsock_recvmsg_nonblock): ditto [ruby-core:71439] [Feature #11339] * ext/socket/rubysocket.h: adjust prototypes for above * ext/socket/basicsocket.c (rsock_init_basicsocket): adjust private methods * ext/socket/lib/socket.rb (BasicSocket#recvmsg): wrapper method (BasicSocket#recvmsg_nonblock): ditto target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52550) [x86_64-linux]) target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52550) [x86_64-linux] ----------------------------------------------------------- recvmsg_nonblock require 'socket' nr = 1_000_000 i = 0 msg = '.' buf = '.' begin r, w = UNIXSocket.pair(:SEQPACKET) while i < nr i += 1 w.sendmsg(msg) r.recvmsg_nonblock(1, exception: false) end ensure r.close w.close end ----------------------------------------------------------- raw data: [["recvmsg_nonblock", [[3.721687912940979, 3.6072621569037437, 3.580637402832508, 3.614185404032469, 3.6029579415917397], [2.4694008752703667, 2.4908322244882584, 2.5051278844475746, 2.5037173740565777, 2.548359278589487]]]] Elapsed time: 30.646087052 (sec) ----------------------------------------------------------- benchmark results: minimum results in each 5 measurements. Execution time (sec) name a b recvmsg_nonblock 3.581 2.469 Speedup ratio: compare with the result of `a' (greater is better) name b recvmsg_nonblock 1.450 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52602 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/socket/lib')
-rw-r--r--ext/socket/lib/socket.rb71
1 files changed, 71 insertions, 0 deletions
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
index fed1d43e34..9e85318c1b 100644
--- a/ext/socket/lib/socket.rb
+++ b/ext/socket/lib/socket.rb
@@ -324,6 +324,77 @@ class BasicSocket < IO
def recv_nonblock(len, flag = 0, str = nil, exception: true)
__recv_nonblock(len, flag, str, exception)
end
+
+ # call-seq:
+ # basicsocket.recvmsg(maxmesglen=nil, flags=0, maxcontrollen=nil, opts={}) => [mesg, sender_addrinfo, rflags, *controls]
+ #
+ # recvmsg receives a message using recvmsg(2) system call in blocking manner.
+ #
+ # _maxmesglen_ is the maximum length of mesg to receive.
+ #
+ # _flags_ is bitwise OR of MSG_* constants such as Socket::MSG_PEEK.
+ #
+ # _maxcontrollen_ is the maximum length of controls (ancillary data) to receive.
+ #
+ # _opts_ is option hash.
+ # Currently :scm_rights=>bool is the only option.
+ #
+ # :scm_rights option specifies that application expects SCM_RIGHTS control message.
+ # If the value is nil or false, application don't expects SCM_RIGHTS control message.
+ # In this case, recvmsg closes the passed file descriptors immediately.
+ # This is the default behavior.
+ #
+ # If :scm_rights value is neither nil nor false, application expects SCM_RIGHTS control message.
+ # In this case, recvmsg creates IO objects for each file descriptors for
+ # Socket::AncillaryData#unix_rights method.
+ #
+ # The return value is 4-elements array.
+ #
+ # _mesg_ is a string of the received message.
+ #
+ # _sender_addrinfo_ is a sender socket address for connection-less socket.
+ # It is an Addrinfo object.
+ # For connection-oriented socket such as TCP, sender_addrinfo is platform dependent.
+ #
+ # _rflags_ is a flags on the received message which is bitwise OR of MSG_* constants such as Socket::MSG_TRUNC.
+ # It will be nil if the system uses 4.3BSD style old recvmsg system call.
+ #
+ # _controls_ is ancillary data which is an array of Socket::AncillaryData objects such as:
+ #
+ # #<Socket::AncillaryData: AF_UNIX SOCKET RIGHTS 7>
+ #
+ # _maxmesglen_ and _maxcontrollen_ can be nil.
+ # In that case, the buffer will be grown until the message is not truncated.
+ # Internally, MSG_PEEK is used and MSG_TRUNC/MSG_CTRUNC are checked.
+ #
+ # recvmsg can be used to implement recv_io as follows:
+ #
+ # mesg, sender_sockaddr, rflags, *controls = sock.recvmsg(:scm_rights=>true)
+ # controls.each {|ancdata|
+ # if ancdata.cmsg_is?(:SOCKET, :RIGHTS)
+ # return ancdata.unix_rights[0]
+ # end
+ # }
+ def recvmsg(dlen = 4096, flags = 0, clen = 4096, scm_rights: false)
+ __recvmsg(dlen, flags, clen, scm_rights)
+ end
+
+ # call-seq:
+ # basicsocket.recvmsg_nonblock(maxdatalen=nil, flags=0, maxcontrollen=nil, opts={}) => [data, sender_addrinfo, rflags, *controls]
+ #
+ # recvmsg receives a message using recvmsg(2) system call in non-blocking manner.
+ #
+ # It is similar to BasicSocket#recvmsg
+ # but non-blocking flag is set before the system call
+ # and it doesn't retry the system call.
+ #
+ # By specifying `exception: false`, the _opts_ hash allows you to indicate
+ # that recvmsg_nonblock should not raise an IO::WaitWritable exception, but
+ # return the symbol :wait_writable instead.
+ def recvmsg_nonblock(dlen = 4096, flags = 0, clen = 4096,
+ scm_rights: false, exception: true)
+ __recvmsg_nonblock(dlen, flags, clen, scm_rights, exception)
+ end
end
class Socket < BasicSocket