################################################################################
#  THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY  #
#  Please refer to the README for information about making permanent changes.  #
################################################################################

module CZMQ
  module FFI
    
    # event-driven reactor
    class Zloop
      class DestroyedError < RuntimeError; end
      
      # Boilerplate for self pointer, initializer, and finalizer
      class << self
        alias :__new :new
      end
      def initialize ptr, finalize=true
        @ptr = ptr
        if @ptr.null?
          @ptr = nil # Remove null pointers so we don't have to test for them.
        elsif finalize
          @finalizer = self.class.send :create_finalizer_for, @ptr
          ObjectSpace.define_finalizer self, @finalizer
        end
      end
      def self.create_finalizer_for ptr
        Proc.new do
          ptr_ptr = ::FFI::MemoryPointer.new :pointer
          ptr_ptr.write_pointer ptr
          ::CZMQ::FFI.zloop_destroy ptr_ptr
        end
      end
      def null?
        !@ptr or ptr.null?
      end
      # Return internal pointer
      def __ptr
        raise DestroyedError unless @ptr
        @ptr
      end
      # Nullify internal pointer and return pointer pointer
      def __ptr_give_ref
        raise DestroyedError unless @ptr
        ptr_ptr = ::FFI::MemoryPointer.new :pointer
        ptr_ptr.write_pointer @ptr
        ObjectSpace.undefine_finalizer self if @finalizer
        @finalizer = nil
        @ptr = nil
        ptr_ptr
      end
      
      # Create a new callback of the following type:
      # Callback function for reactor socket activity
      #     typedef int (zloop_reader_fn) (                
      #         zloop_t *loop, zsock_t *reader, void *arg);
      #
      # WARNING: If your Ruby code doesn't retain a reference to the
      #   FFI::Function object after passing it to a C function call,
      #   it may be garbage collected while C still holds the pointer,
      #   potentially resulting in a segmentation fault.
      def self.reader_fn
        ::FFI::Function.new :int, [:pointer, :pointer, :pointer], blocking: true do |loop, reader, arg|
          loop = Zloop.__new loop, false
          reader = Zsock.__new reader, false
          yield loop, reader, arg
        end
      end
      
      # Create a new callback of the following type:
      # Callback function for reactor events (low-level)
      #     typedef int (zloop_fn) (                            
      #         zloop_t *loop, zmq_pollitem_t *item, void *arg);
      #
      # WARNING: If your Ruby code doesn't retain a reference to the
      #   FFI::Function object after passing it to a C function call,
      #   it may be garbage collected while C still holds the pointer,
      #   potentially resulting in a segmentation fault.
      def self.fn
        ::FFI::Function.new :int, [:pointer, :pointer, :pointer], blocking: true do |loop, item, arg|
          loop = Zloop.__new loop, false
          yield loop, item, arg
        end
      end
      
      # Create a new callback of the following type:
      # Callback for reactor timer events
      #     typedef int (zloop_timer_fn) (              
      #         zloop_t *loop, int timer_id, void *arg);
      #
      # WARNING: If your Ruby code doesn't retain a reference to the
      #   FFI::Function object after passing it to a C function call,
      #   it may be garbage collected while C still holds the pointer,
      #   potentially resulting in a segmentation fault.
      def self.timer_fn
        ::FFI::Function.new :int, [:pointer, :int, :pointer], blocking: true do |loop, timer_id, arg|
          loop = Zloop.__new loop, false
          yield loop, timer_id, arg
        end
      end
      
      # Create a new zloop reactor
      def self.new
        ptr = ::CZMQ::FFI.zloop_new
        
        __new ptr
      end
      
      # Destroy a reactor
      def destroy
        return unless @ptr
        self_p = __ptr_give_ref
        result = ::CZMQ::FFI.zloop_destroy self_p
        result
      end
      
      # Register socket reader with the reactor. When the reader has messages, 
      # the reactor will call the handler, passing the arg. Returns 0 if OK, -1
      # if there was an error. If you register the same socket more than once, 
      # each instance will invoke its corresponding handler.                   
      def reader sock, handler, arg
        raise DestroyedError unless @ptr
        sock = sock.__ptr if sock
        result = ::CZMQ::FFI.zloop_reader @ptr, sock, handler, arg
        result
      end
      
      # Cancel a socket reader from the reactor. If multiple readers exist for
      # same socket, cancels ALL of them.                                     
      def reader_end sock
        raise DestroyedError unless @ptr
        sock = sock.__ptr if sock
        result = ::CZMQ::FFI.zloop_reader_end @ptr, sock
        result
      end
      
      # Configure a registered reader to ignore errors. If you do not set this,
      # then readers that have errors are removed from the reactor silently.   
      def reader_set_tolerant sock
        raise DestroyedError unless @ptr
        sock = sock.__ptr if sock
        result = ::CZMQ::FFI.zloop_reader_set_tolerant @ptr, sock
        result
      end
      
      # Register low-level libzmq pollitem with the reactor. When the pollitem  
      # is ready, will call the handler, passing the arg. Returns 0 if OK, -1   
      # if there was an error. If you register the pollitem more than once, each
      # instance will invoke its corresponding handler. A pollitem with         
      # socket=NULL and fd=0 means 'poll on FD zero'.                           
      def poller item, handler, arg
        raise DestroyedError unless @ptr
        result = ::CZMQ::FFI.zloop_poller @ptr, item, handler, arg
        result
      end
      
      # Cancel a pollitem from the reactor, specified by socket or FD. If both
      # are specified, uses only socket. If multiple poll items exist for same
      # socket/FD, cancels ALL of them.                                       
      def poller_end item
        raise DestroyedError unless @ptr
        result = ::CZMQ::FFI.zloop_poller_end @ptr, item
        result
      end
      
      # Configure a registered poller to ignore errors. If you do not set this,
      # then poller that have errors are removed from the reactor silently.    
      def poller_set_tolerant item
        raise DestroyedError unless @ptr
        result = ::CZMQ::FFI.zloop_poller_set_tolerant @ptr, item
        result
      end
      
      # Register a timer that expires after some delay and repeats some number of
      # times. At each expiry, will call the handler, passing the arg. To run a  
      # timer forever, use 0 times. Returns a timer_id that is used to cancel the
      # timer in the future. Returns -1 if there was an error.                   
      def timer delay, times, handler, arg
        raise DestroyedError unless @ptr
        delay = Integer(delay)
        times = Integer(times)
        result = ::CZMQ::FFI.zloop_timer @ptr, delay, times, handler, arg
        result
      end
      
      # Cancel a specific timer identified by a specific timer_id (as returned by
      # zloop_timer).                                                            
      def timer_end timer_id
        raise DestroyedError unless @ptr
        timer_id = Integer(timer_id)
        result = ::CZMQ::FFI.zloop_timer_end @ptr, timer_id
        result
      end
      
      # Register a ticket timer. Ticket timers are very fast in the case where   
      # you use a lot of timers (thousands), and frequently remove and add them. 
      # The main use case is expiry timers for servers that handle many clients, 
      # and which reset the expiry timer for each message received from a client.
      # Whereas normal timers perform poorly as the number of clients grows, the 
      # cost of ticket timers is constant, no matter the number of clients. You  
      # must set the ticket delay using zloop_set_ticket_delay before creating a 
      # ticket. Returns a handle to the timer that you should use in             
      # zloop_ticket_reset and zloop_ticket_delete.                              
      def ticket handler, arg
        raise DestroyedError unless @ptr
        result = ::CZMQ::FFI.zloop_ticket @ptr, handler, arg
        result
      end
      
      # Reset a ticket timer, which moves it to the end of the ticket list and
      # resets its execution time. This is a very fast operation.             
      def ticket_reset handle
        raise DestroyedError unless @ptr
        result = ::CZMQ::FFI.zloop_ticket_reset @ptr, handle
        result
      end
      
      # Delete a ticket timer. We do not actually delete the ticket here, as    
      # other code may still refer to the ticket. We mark as deleted, and remove
      # later and safely.                                                       
      def ticket_delete handle
        raise DestroyedError unless @ptr
        result = ::CZMQ::FFI.zloop_ticket_delete @ptr, handle
        result
      end
      
      # Set the ticket delay, which applies to all tickets. If you lower the   
      # delay and there are already tickets created, the results are undefined.
      def set_ticket_delay ticket_delay
        raise DestroyedError unless @ptr
        ticket_delay = Integer(ticket_delay)
        result = ::CZMQ::FFI.zloop_set_ticket_delay @ptr, ticket_delay
        result
      end
      
      # Set hard limit on number of timers allowed. Setting more than a small  
      # number of timers (10-100) can have a dramatic impact on the performance
      # of the reactor. For high-volume cases, use ticket timers. If the hard  
      # limit is reached, the reactor stops creating new timers and logs an    
      # error.                                                                 
      def set_max_timers max_timers
        raise DestroyedError unless @ptr
        max_timers = Integer(max_timers)
        result = ::CZMQ::FFI.zloop_set_max_timers @ptr, max_timers
        result
      end
      
      # Set verbose tracing of reactor on/off
      def set_verbose verbose
        raise DestroyedError unless @ptr
        verbose = !(0==verbose||!verbose) # boolean
        result = ::CZMQ::FFI.zloop_set_verbose @ptr, verbose
        result
      end
      
      # Start the reactor. Takes control of the thread and returns when the 0MQ  
      # context is terminated or the process is interrupted, or any event handler
      # returns -1. Event handlers may register new sockets and timers, and      
      # cancel sockets. Returns 0 if interrupted, -1 if cancelled by a handler.  
      def start
        raise DestroyedError unless @ptr
        result = ::CZMQ::FFI.zloop_start @ptr
        result
      end
      
      # Ignore zsys_interrupted flag in this loop. By default, a zloop_start will 
      # exit as soon as it detects zsys_interrupted is set to something other than
      # zero. Calling zloop_ignore_interrupts will supress this behavior.         
      def ignore_interrupts
        raise DestroyedError unless @ptr
        result = ::CZMQ::FFI.zloop_ignore_interrupts @ptr
        result
      end
      
      # Self test of this class
      def self.test verbose
        verbose = !(0==verbose||!verbose) # boolean
        result = ::CZMQ::FFI.zloop_test verbose
        result
      end
    end
    
  end
end

################################################################################
#  THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY  #
#  Please refer to the README for information about making permanent changes.  #
################################################################################
