#line 1 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
/* -*- c -*-
|| This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
|| $Id: Shuffler.cmod,v 1.32 2005/03/22 16:56:28 grubba Exp $
*/

#include "global.h"
#include "stralloc.h"
RCSID("$Id: Shuffler.cmod,v 1.32 2005/03/22 16:56:28 grubba Exp $");
#include "pike_macros.h"
#include "interpret.h"
#include "threads.h"
#include "program.h"
#include "program_id.h"
#include "object.h"
#include "operators.h"
#include "fdlib.h"
#include "fd_control.h"
#include "backend.h"
#include "module_support.h"
#include "array.h"
#include "builtin_functions.h"
#include "bignum.h"

#include "shuffler.h"
#include "sources.h"

#if 0
#include <stdio.h>
#define SHUFFLE_DEBUG1(fmt, arg1)			fprintf(stderr,"Shuffle[%p]:" fmt, arg1)
#define SHUFFLE_DEBUG2(fmt, arg1, arg2)			fprintf(stderr,"Shuffle[%p]:" fmt, arg1, arg2)
#define SHUFFLE_DEBUG3(fmt, arg1, arg2, arg3)		fprintf(stderr,"Shuffle[%p]:" fmt, arg1, arg2, arg3)
#define SHUFFLE_DEBUG4(fmt, arg1, arg2, arg3, arg4)	fprintf(stderr,"Shuffle[%p]:" fmt, arg1, arg2, arg3, arg4)
#else
#define SHUFFLE_DEBUG1(fmt, arg1)
#define SHUFFLE_DEBUG2(fmt, arg1, arg2)
#define SHUFFLE_DEBUG3(fmt, arg1, arg2, arg3)
#define SHUFFLE_DEBUG4(fmt, arg1, arg2, arg3, arg4)
#endif
#define BLOCK 8192
static void free_source( struct source *s )
{
  debug_malloc_touch(s);
  if( s->free_source ) s->free_source( s );
  free( s );
}

extern struct program *Shuffler_program;

/*! @module Shuffler
 */

/*! @class Throttler
 *!
 *! @note
 *!  This is an interface that all @[Throttler]s must implement.
 *!  It's not an actual class in this module.
 *!
 *! @decl void request( Shuffle shuffle, int amount, function(int:void) callback )
 *! This function is called when the @[Shuffle] wants to send some
 *! data to a client.
 *!
 *! When data can be sent, the @[callback] function should be called
 *! with the amount of data that can be sent as the argument.
 *!
 *! @decl void give_back( Shuffle shuffle, int amount ) 
 *! This function will be called by the @[Shuffle] object to report
 *! that some data assigned to it by this throttler was unusued, and
 *! can be given to another @[Shuffle] object instead.
 */
/*! @endclass
 */

/*! @class Shuffle
 *! This class contains the state for one ongoing data
 *! shuffling operation. To create a @[Shuffle] instance, use the
 *! @[Shuffler()->shuffle] method.
 *! 
 */


#undef class_Shuffle_defined
#define class_Shuffle_defined
struct program *Shuffle_program=NULL;
static int Shuffle_program_fun_num=-1;

#undef var_box_Shuffle_defined
#define var_box_Shuffle_defined

#undef var_shuffler_Shuffle_defined
#define var_shuffler_Shuffle_defined
/*! @decl Shuffler shuffler;
   *! The @[Shuffler] that owns this @[Shuffle] object
   *! 
  */
  
#undef var_throttler_Shuffle_defined
#define var_throttler_Shuffle_defined
/*! @decl Throttler throttler;
   *! The @[Throttler] that is associated with this @[Shuffle] object,
   *! if any.
   *! 
  */

  
#undef var_done_callback_Shuffle_defined
#define var_done_callback_Shuffle_defined

#undef var_request_arg_Shuffle_defined
#define var_request_arg_Shuffle_defined

#undef var_current_source_Shuffle_defined
#define var_current_source_Shuffle_defined

#undef var_last_source_Shuffle_defined
#define var_last_source_Shuffle_defined

#undef var_file_obj_Shuffle_defined
#define var_file_obj_Shuffle_defined

#undef var_callback_Shuffle_defined
#define var_callback_Shuffle_defined

#undef var_write_callback_Shuffle_defined
#define var_write_callback_Shuffle_defined

#undef var_sent_Shuffle_defined
#define var_sent_Shuffle_defined

#undef var_state_Shuffle_defined
#define var_state_Shuffle_defined

#undef var_leftovers_Shuffle_defined
#define var_leftovers_Shuffle_defined

#undef THIS
#define THIS ((struct Shuffle_struct *)(Pike_interpreter.frame_pointer->current_storage))

#undef THIS_SHUFFLE
#define THIS_SHUFFLE ((struct Shuffle_struct *)(Pike_interpreter.frame_pointer->current_storage))

#undef OBJ2_SHUFFLE
#define OBJ2_SHUFFLE(o) ((struct Shuffle_struct *)(o->storage+Shuffle_storage_offset))

#undef GET_SHUFFLE_STORAGE
#define GET_SHUFFLE_STORAGE ((struct Shuffle_struct *)(o->storage+Shuffle_storage_offset)
static ptrdiff_t Shuffle_storage_offset;
struct Shuffle_struct {

#ifdef var_box_Shuffle_defined
#line 84 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct fd_callback_box box;
#endif /* var_box_Shuffle_defined */

#ifdef var_shuffler_Shuffle_defined
  struct object * shuffler;

#endif /* var_shuffler_Shuffle_defined */

#ifdef var_throttler_Shuffle_defined
  struct object * throttler;

#endif /* var_throttler_Shuffle_defined */

#ifdef var_done_callback_Shuffle_defined
  struct svalue done_callback;

#endif /* var_done_callback_Shuffle_defined */

#ifdef var_request_arg_Shuffle_defined
  struct svalue request_arg;

#endif /* var_request_arg_Shuffle_defined */

#ifdef var_current_source_Shuffle_defined
#line 102 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct source *current_source;
#endif /* var_current_source_Shuffle_defined */

#ifdef var_last_source_Shuffle_defined
#line 103 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct source *last_source;
#endif /* var_last_source_Shuffle_defined */

#ifdef var_file_obj_Shuffle_defined
#line 104 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct object *file_obj;
#endif /* var_file_obj_Shuffle_defined */

#ifdef var_callback_Shuffle_defined
#line 105 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
int callback;
#endif /* var_callback_Shuffle_defined */

#ifdef var_write_callback_Shuffle_defined
#line 106 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
int write_callback;
#endif /* var_write_callback_Shuffle_defined */

#ifdef var_sent_Shuffle_defined
#line 108 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
int sent;
#endif /* var_sent_Shuffle_defined */

#ifdef var_state_Shuffle_defined
#line 109 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
ShuffleState state;
#endif /* var_state_Shuffle_defined */

#ifdef var_leftovers_Shuffle_defined
#line 111 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct data leftovers;
#endif /* var_leftovers_Shuffle_defined */
};
static void _send_more( struct Shuffle_struct *t );
  static void __set_callbacks( struct Shuffle_struct *t )
  {
    SHUFFLE_DEBUG2("__set_calllbacks(%s)\n", t,(t->box.fd>0?"C":"Pike") );
    if( t->box.fd >= 0 )
      set_fd_callback_events(&t->box, PIKE_BIT_FD_WRITE);
    else if( t->file_obj && t->file_obj->prog )
    {
      ref_push_object( t->box.ref_obj );
      Pike_sp[-1].type = PIKE_T_FUNCTION;
      Pike_sp[-1].subtype = t->write_callback;
      safe_apply( t->file_obj, "set_write_callback", 1 );
      pop_stack();
    }
    else {
      SHUFFLE_DEBUG1("EEP: No destination! Cannot set callbacks\n",t);
    }
  }
  
  static void __remove_callbacks( struct Shuffle_struct *t )
  {
    SHUFFLE_DEBUG2("__remove_calllbacks(%s)\n", t, (t->box.fd>=0?"C":"Pike") );
    if( t->box.fd >= 0 )
      set_fd_callback_events(&t->box, 0);
    else if( t->file_obj && t->file_obj->prog )
    {
      push_int(0);
      safe_apply( t->file_obj, "set_write_callback", 1 );
      pop_stack();
    }
    else {
      SHUFFLE_DEBUG1("EEP: No destination! Cannot remove callbacks\n",t);
    }
  }

  static int got_shuffler_event(struct fd_callback_box*box, int event) {
#ifdef PIKE_DEBUG
    if (event != PIKE_FD_WRITE)
      Pike_fatal ("Got unexpected event %d.\n", event);
#endif
    _send_more((struct Shuffle_struct*)
     ((char*)box-offsetof(struct Shuffle_struct,box)));
  }
  
  #define f_Shuffle_set_throttler_defined
ptrdiff_t f_Shuffle_set_throttler_fun_num = 0;
void f_Shuffle_set_throttler(INT32 args) {
#line 158 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct object * t;
#line 158 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 1) wrong_number_of_args_error("set_throttler",args,1);
#line 158 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(Pike_sp[0-1].type != PIKE_T_OBJECT) SIMPLE_BAD_ARG_ERROR("set_throttler",1,"object");
#line 158 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
debug_malloc_pass(t=Pike_sp[0-1].u.object);
/*! @decl void set_throttler(Throttler t)
   *! Calling this function overrides the @[Shuffler] global throttler.
   *! 
  */
    
#line 164 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    SHUFFLE_DEBUG2("set_throttler(%p)\n", THIS, t );
    if( THIS->throttler )
      free_object( THIS->throttler );
    THIS->throttler = t;
    debug_malloc_touch(THIS->throttler);
    Pike_sp--;
    push_int(0);
  }

  }
#define f_Shuffle_sent_data_defined
ptrdiff_t f_Shuffle_sent_data_fun_num = 0;
void f_Shuffle_sent_data(INT32 args) {
#line 174 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 0) wrong_number_of_args_error("sent_data",args,0);
/*! @decl int sent_data()
   *! Returns the amount of data that has been sent so far.
   *! 
  */
    
#line 180 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    SHUFFLE_DEBUG2("sent_data() --> %d\n", THIS, THIS->sent );
    do { INT_TYPE ret_=(THIS->sent);  push_int(ret_); return; }while(0);
#line 183 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
}

  }
#define f_Shuffle_state_defined
ptrdiff_t f_Shuffle_state_fun_num = 0;
void f_Shuffle_state(INT32 args) {
#line 185 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 0) wrong_number_of_args_error("state",args,0);
/*! @decl int state()
   *! Returns the current state of the shuffler.
   *! This is one of the following:
   *!   @[INITIAL], 
   *!   @[RUNNING], 
   *!   @[PAUSED], 
   *!   @[DONE], 
   *!   @[WRITE_ERROR], 
   *!   @[READ_ERROR] and
   *!   @[USER_ABORT]
   *!   
  */
    
#line 199 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    SHUFFLE_DEBUG2("state() --> %d\n", THIS, THIS->state );
    do { INT_TYPE ret_=(THIS->state);  push_int(ret_); return; }while(0);
#line 202 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
}

  }

#undef internal_init_Shuffle_defined
#define internal_init_Shuffle_defined

#undef Shuffle_event_handler_defined
#define Shuffle_event_handler_defined
static void init_Shuffle_struct(void)
#line 205 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    THIS->leftovers.do_free = 0;
    THIS->shuffler = 0;
    THIS->throttler = 0;
    THIS->sent = 0;
    THIS->done_callback.type = PIKE_T_INT;
    THIS->request_arg.type = PIKE_T_INT;
    THIS->request_arg.u.integer = 0;
    THIS->leftovers.len = 0;
    THIS->current_source = NULL;
    THIS->file_obj = NULL;
    THIS->state = INITIAL;
    THIS->callback = 
      find_identifier("send_more_callback",Pike_fp->current_object->prog);

    THIS->write_callback = 
      find_identifier("write_callback",Pike_fp->current_object->prog);
    THIS->box.backend = NULL;
    THIS->box.ref_obj = Pike_fp->current_object;
    THIS->box.fd = -1;
    debug_malloc_touch(THIS->box.ref_obj);
    
    SHUFFLE_DEBUG1("init()\n", THIS );
  }

  
#undef internal_exit_Shuffle_defined
#define internal_exit_Shuffle_defined

#undef Shuffle_event_handler_defined
#define Shuffle_event_handler_defined
static void exit_Shuffle_struct(void)
#line 231 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    SHUFFLE_DEBUG1("exit()\n", THIS );

    if(THIS->box.fd >= 0) {
      push_int( THIS->box.fd );
      unhook_fd_callback_box(&THIS->box);
      if(THIS->file_obj)
        safe_apply( THIS->file_obj, "take_fd", 1 );
      pop_stack();
    }

    if( THIS->file_obj )
    {
      free_object( THIS->file_obj );
      THIS->file_obj = 0;
    }
    while( THIS->current_source )
    {
      struct source *n = THIS->current_source->next;
      free_source( THIS->current_source );
      THIS->current_source = n;
    }

    if( THIS->leftovers.data && THIS->leftovers.do_free )
    {
      debug_malloc_touch(THIS->leftovers.data);
      free( THIS->leftovers.data );
    }
  }
  
  static void __send_more_callback( struct Shuffle_struct *t, int amount );
  static void _request( struct Shuffle_struct *t, int amount )
  {
    SHUFFLE_DEBUG3("_request(%d) from %p\n", t, amount, t->throttler );
    if( t->throttler && t->throttler->prog )
    {
      __remove_callbacks( t );
      debug_malloc_touch( t->throttler );
      debug_malloc_touch( t->box.ref_obj );
      ref_push_object( t->box.ref_obj );
      push_int( amount );
      ref_push_object( t->box.ref_obj );
      Pike_sp[-1].type = PIKE_T_FUNCTION;
      Pike_sp[-1].subtype = t->callback;
      push_svalue( &t->request_arg );
      safe_apply( t->throttler, "request", 4 );
      pop_stack();
    }
    else /* bypass the pike function calling for the case
  	* when no throttling is done 
  	*/
      __send_more_callback( t, amount );
  }
  
  static void _send_more( struct Shuffle_struct *t )
  {
    int l = BLOCK;
    SHUFFLE_DEBUG2("_send_more(%d)\n", t, t->box.fd );
    if( t->leftovers.len > 0 )
      l = t->leftovers.len;
    _request( t, l );
  }
  
  static void _set_callbacks( struct Shuffle_struct *t )
  {
    SHUFFLE_DEBUG1("_set_callbacks()\n", t );
    if( t->current_source && t->current_source->setup_callbacks )
      t->current_source->setup_callbacks( t->current_source );
    __set_callbacks( t );
  }
  
  static void _remove_callbacks( struct Shuffle_struct *t )
  {
    SHUFFLE_DEBUG1("_remove_callbacks()\n",t );
    if( t->current_source && t->current_source->remove_callbacks )
      t->current_source->remove_callbacks( t->current_source );
    __remove_callbacks( t );
  }
  
  static void _all_done( struct Shuffle_struct *t, int reason )
  {
    SHUFFLE_DEBUG2("_all_done(%d)\n", t,reason );

    /* We should set the reason for being done first of all */
    switch( reason )
    {
      case 0: t->state = DONE; break;
      case 1: t->state = WRITE_ERROR; break;
      case 2: t->state = USER_ABORT; break;
      case 3: t->state = READ_ERROR; break;
    }

    /* Remove our callbacks. */
    _remove_callbacks( t );

    if(t->box.fd >= 0) {
      push_int( t->box.fd );
      unhook_fd_callback_box(&t->box);
      if(t->file_obj)
        safe_apply(t->file_obj, "take_fd", 1 );
      pop_stack();
      THIS->box.fd = -1;
    }
    
    debug_malloc_touch( t->box.ref_obj );
    ref_push_object( t->box.ref_obj );

    /* If a callback exists, we call it before destroying
     * source and destination
     */
    if( t->done_callback.type != PIKE_T_INT )
    {
      SHUFFLE_DEBUG3("_all_done(%d): Calling done callback: %p\n", t,
		    reason, t->done_callback.u.object);
      push_svalue( &t->done_callback );
      
      ref_push_object( t->box.ref_obj );
      push_int( reason );

      apply_svalue( Pike_sp-3, 2 );
      pop_stack();
      pop_stack();
    }

    /* It might have been destroyed. */
    if( t->shuffler && t->shuffler->prog )
    {
      debug_malloc_touch( t->shuffler );
      safe_apply( t->shuffler, "___remove_shuffle", 1 );
    }
    pop_stack();

    /* Destroy file_obj if any. */
    if( t->file_obj )
    {
      debug_malloc_touch( t->file_obj );
      free_object( t->file_obj );
      t->file_obj = 0;
    }

    /* Destroy all our sources. */
    while( t->current_source )
    {
      struct source *n = t->current_source->next;
      debug_malloc_touch( t->current_source );
      free_source( t->current_source );
      t->current_source = n;
    }

    /* Free any data left in pipe. */
    if( t->leftovers.data && t->leftovers.do_free )
    {
      debug_malloc_touch( t->leftovers.data );
      free( t->leftovers.data );
    }

    t->leftovers.data = 0;
  }

  #define f_Shuffle_set_done_callback_defined
ptrdiff_t f_Shuffle_set_done_callback_fun_num = 0;
void f_Shuffle_set_done_callback(INT32 args) {
#line 390 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct svalue * cb;
#line 390 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 1) wrong_number_of_args_error("set_done_callback",args,1);
#line 390 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
cb=Pike_sp+0-1; dmalloc_touch_svalue(Pike_sp+0-1);
/*! @decl void set_done_callback( function(Shuffle,int:void) cb )
    *! Sets the done callback. This function will be called when all
    *! sources have been processed, or if an error occurs.
    *! 
    */
    
#line 397 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    SHUFFLE_DEBUG2("set_done_callback(%p)\n", THIS, cb->u.object );
    assign_svalue( &THIS->done_callback,cb);
  }

  }
#define f_Shuffle_set_request_arg_defined
ptrdiff_t f_Shuffle_set_request_arg_fun_num = 0;
void f_Shuffle_set_request_arg(INT32 args) {
#line 402 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct svalue * arg;
#line 402 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 1) wrong_number_of_args_error("set_request_arg",args,1);
#line 402 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
arg=Pike_sp+0-1; dmalloc_touch_svalue(Pike_sp+0-1);
/*! @decl void set_request_arg( mixed arg )
    *!
    *! Sets the extra argument sent to @[Throttler()->request()] and
    *! @[Throttler()->give_back].
    *! 
    */
    
#line 410 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    SHUFFLE_DEBUG2("set_request_arg(%p)\n", THIS, arg->u.object );
    assign_svalue( &THIS->request_arg, arg );
  }
  
  }
#line 415 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
static void _give_back( struct Shuffle_struct *t, int amount )
  {
    SHUFFLE_DEBUG2("_give_back(%d)\n", t, amount );
    if( t->throttler && t->throttler->prog )
    {
      ref_push_object( t->box.ref_obj );
      debug_malloc_touch( t->box.ref_obj );
      debug_malloc_touch( t->throttler );
      push_int( amount );
      push_svalue( &t->request_arg );
      safe_apply( t->throttler, "give_back", 3 );
      pop_stack();
    }
  }

  static void __send_more_callback( struct Shuffle_struct *t, int amount )
  {
    int sent = 0;
    SHUFFLE_DEBUG2("__send_more_callback(%d)\n", t, amount );
    while( t->leftovers.len < 1 )
    {
      while( t->current_source && t->current_source->eof )
      {
	struct source *n = t->current_source->next;
	SHUFFLE_DEBUG2("__send_more_callback(): source done: %p\n", t, t->current_source );
	if( t->current_source->remove_callbacks )
	  t->current_source->remove_callbacks( t->current_source );
	free_source( t->current_source );
	t->current_source = n;
	if( n && n->setup_callbacks )
	  n->setup_callbacks( n );
      }

      if( !t->current_source )
      {
	SHUFFLE_DEBUG1("__send_more_callback(): no sources\n", t );
	_give_back( t, amount );
	_all_done( t, 0 );
	return;
      }

      t->leftovers = t->current_source->get_data( t->current_source,
						  MAXIMUM(amount,8192) );

      if( t->leftovers.len == -2 )
      {
	/* come back later (nonblocking source without more data to read) */
	SHUFFLE_DEBUG1("__send_more_callback(): read pending\n", t );
	__remove_callbacks( t );
	t->current_source->set_callback( t->current_source,
					 (void *)_set_callbacks, t );
	_give_back( t, amount );
	return;
      }
      else if( t->leftovers.len < 0 )
      {
	SHUFFLE_DEBUG1("__send_more_callback(): read error\n", t );
	/* read error */
	_give_back( t, amount );
	_all_done( t, 3 );
	return;
      }
    }
    /* Now it's time to actually send the data. */
    SHUFFLE_DEBUG2("__send_more_callback(): sending(%d)\n", t,
		  MINIMUM(amount,t->leftovers.len));
    sent = -1;
    if( t->box.fd >= 0 )
    {
      THREADS_ALLOW();
      sent = fd_write( t->box.fd, t->leftovers.data+t->leftovers.off,
		       MINIMUM(amount,t->leftovers.len) );
      THREADS_DISALLOW();
    }
    else if( t->file_obj )
    {
      push_string( make_shared_binary_string(
		     t->leftovers.data+t->leftovers.off,
		    MINIMUM(amount,t->leftovers.len) ) );
      apply( t->file_obj, "write", 1 );
      if( Pike_sp[-1].type == PIKE_T_INT )
	sent = Pike_sp[-1].u.integer;
      else
      {
	SHUFFLE_DEBUG2("Oops: write returned object of type %d, not integer\n",
		      t, Pike_sp[-1].type );
      }
      pop_stack();
    }
    SHUFFLE_DEBUG3("__send_more_callback(): sending(%d): sent %d\n", t,
		  MINIMUM(t->leftovers.len,amount),sent );

    if( sent < 0 )
    {
      _give_back( t, amount );
      _all_done( t, 1 );
      return;
    }
    if( sent )
    {
      t->sent += sent;
      if( t->leftovers.len == sent )
      {
	t->leftovers.len = 0;
	if( t->leftovers.do_free )
	  free( t->leftovers.data );
      }
      else
      {
	t->leftovers.len -= sent;
	t->leftovers.off += sent;
      }
    }
    if( sent < amount )
      _give_back( t, amount-sent );
  }

  /*! @decl void send_more_callback( int amount )
   */
  #define f_Shuffle_send_more_callback_defined
ptrdiff_t f_Shuffle_send_more_callback_fun_num = 0;
void f_Shuffle_send_more_callback(INT32 args) {
#line 534 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
INT_TYPE amount;
#line 534 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 1) wrong_number_of_args_error("send_more_callback",args,1);
#line 534 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(Pike_sp[0-1].type != PIKE_T_INT) SIMPLE_BAD_ARG_ERROR("send_more_callback",1,"int");
amount=Pike_sp[0-1].u.integer;
{
    SHUFFLE_DEBUG2("send_more_callback(%d)\n", THIS,amount );
    if( THIS->state == RUNNING )
    {
      __set_callbacks( THIS );
      __send_more_callback( THIS, amount );
    }
    else
      _give_back( THIS, amount );
  }

  }
/*! @decl void write_callback( mixed|void x )
   */
  #define f_Shuffle_write_callback_defined
ptrdiff_t f_Shuffle_write_callback_fun_num = 0;
void f_Shuffle_write_callback(INT32 args) {
#line 549 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct svalue * x;
#line 549 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args > 1) wrong_number_of_args_error("write_callback",args,1);
if (args > 0) {
#line 549 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
x=Pike_sp+0-args; dmalloc_touch_svalue(Pike_sp+0-args);
} else x=0;
{
    SHUFFLE_DEBUG1("write_callback()\n", THIS );
    _send_more( THIS );
  }

  }
/*! @decl void create(object fd, object shuffler, mixed throttler,@
   *!                   mixed backend)
   */
  #define f_Shuffle_create_defined
ptrdiff_t f_Shuffle_create_fun_num = 0;
void f_Shuffle_create(INT32 args) {
#line 559 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct object * fd;
struct object * shuffler;
struct svalue * throttler;
struct svalue * backend;
#line 559 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 4) wrong_number_of_args_error("create",args,4);
#line 559 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(Pike_sp[0-4].type != PIKE_T_OBJECT) SIMPLE_BAD_ARG_ERROR("create",1,"object");
#line 559 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
debug_malloc_pass(fd=Pike_sp[0-4].u.object);
if(Pike_sp[1-4].type != PIKE_T_OBJECT) SIMPLE_BAD_ARG_ERROR("create",2,"object");
#line 560 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
debug_malloc_pass(shuffler=Pike_sp[1-4].u.object);
throttler=Pike_sp+2-4; dmalloc_touch_svalue(Pike_sp+2-4);
backend=Pike_sp+3-4; dmalloc_touch_svalue(Pike_sp+3-4);
#line 564 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    struct Backend_struct*be = default_backend;

    if( (args != 4) || !shuffler || !get_storage( shuffler, Shuffler_program ) )
      Pike_error("This class cannot be instantiated directly\n");

    THIS->file_obj = fd;
    add_ref(THIS->file_obj);

    THIS->shuffler = shuffler;
    add_ref(THIS->shuffler);

    if( throttler->type == PIKE_T_OBJECT )
    {
      THIS->throttler = throttler->u.object;
      add_ref(THIS->throttler);
    }

    if (find_identifier("release_fd", fd->prog) < 0)
      change_fd_for_box(&THIS->box, -1);
    else {
      safe_apply( fd, "release_fd", 0 );
      if(backend->type == PIKE_T_OBJECT && backend->u.object)
        be = (struct Backend_struct*)backend->u.object;
      change_fd_for_box(&THIS->box, Pike_sp[-1].u.integer);
      pop_stack();
    }

    if( THIS->box.fd >= 0 )
    {
      set_nonblocking( THIS->box.fd, 1 );
      if(THIS->box.backend)
        set_fd_callback_events(&THIS->box, 0);
      else
        INIT_FD_CALLBACK_BOX(&THIS->box, be, THIS->box.ref_obj,
         THIS->box.fd, 0, got_shuffler_event);
    }
    else
    {
      push_int( 0 ); /* read */
      push_int( 0 ); /* write */
      push_int( 0 ); /* close */
      safe_apply( THIS->file_obj, "set_nonblocking", 3 );
      pop_stack();
    }

    pop_n_elems( args );
    push_int(0);
  }

  }
#define f_Shuffle_start_defined
ptrdiff_t f_Shuffle_start_fun_num = 0;
void f_Shuffle_start(INT32 args) {
#line 614 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 0) wrong_number_of_args_error("start",args,0);
/*! @decl void start();
    *! Start sending data from the sources.
    *! 
    */
    
#line 620 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    if( !THIS->file_obj )
      Pike_error("Cannot start, no destination.\n");
    THIS->state = RUNNING;
    SHUFFLE_DEBUG1("start()\n", THIS );
    _set_callbacks( THIS );
  }

  }
#define f_Shuffle_pause_defined
ptrdiff_t f_Shuffle_pause_fun_num = 0;
void f_Shuffle_pause(INT32 args) {
#line 628 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 0) wrong_number_of_args_error("pause",args,0);
/*! @decl void pause();
    *! Temporarily pause all data transmission
    *! 
    */
    
#line 634 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    THIS->state = PAUSED;
    SHUFFLE_DEBUG1("pause()\n", THIS );
    _remove_callbacks( THIS );
  }

  }
#define f_Shuffle_stop_defined
ptrdiff_t f_Shuffle_stop_fun_num = 0;
void f_Shuffle_stop(INT32 args) {
#line 640 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 0) wrong_number_of_args_error("stop",args,0);
/*! @decl void stop();
    *! Stop all data transmission, and then call the done callback
    *! 
    */
    
#line 646 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    SHUFFLE_DEBUG1("stop()\n", THIS );
    _all_done( THIS, 2 );
  }

  }
#define f_Shuffle_add_source_defined
ptrdiff_t f_Shuffle_add_source_fun_num = 0;
void f_Shuffle_add_source(INT32 args) {
#line 651 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct svalue * source;
#line 651 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct svalue * start;
#line 651 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct svalue * length;
#line 651 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args < 1) wrong_number_of_args_error("add_source",args,1);
#line 651 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args > 3) wrong_number_of_args_error("add_source",args,3);
#line 651 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
source=Pike_sp+0-args; dmalloc_touch_svalue(Pike_sp+0-args);
if (args > 1) {
#line 651 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
start=Pike_sp+1-args; dmalloc_touch_svalue(Pike_sp+1-args);
} else start=0;
if (args > 2) {
#line 651 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
length=Pike_sp+2-args; dmalloc_touch_svalue(Pike_sp+2-args);
} else length=0;
/*! @decl void add_source( mixed source, int|void start, int|void length );
    *! Add a new source to the list of data sources.
    *! The data from the sources will be sent in order.
    *!
    *! If start and length are not specified, the whole source will be
    *! sent, if start but not length is specified, the whole source,
    *! excluding the first @[start] bytes will be sent.
    *!
    *! Currently supported sources
    *! @dl
    *!   @item String
    *!     An ordinary 8-bit wide pike string.
    *!   @item Memory
    *!     An initialized instance of the System.Memory class.
    *!   @item NormalFile
    *!     Stdio.File instance pointing to a normal file.
    *!   @item Stream
    *!     Stdio.File instance pointing to a stream of some kind
    *!     (network socket, named pipe, stdin etc).
    *!   @item Pike-stream
    *!     Stdio.File lookalike with read callback support
    *!     (set_read_callback and set_close_callback).
    *! @enddl
    */
    {
    INT64 rstart=0, rlength=-1;
    struct source *res;

    if( !THIS->file_obj )
      Pike_error("Cannot add source, no destination.\n");

    if( args > 1 )
    {
#ifdef AUTO_BIGNUM
      if( start->type == PIKE_T_OBJECT )
	int64_from_bignum( &rstart, start->u.object );
      else
#endif
	if( start->type == PIKE_T_INT && !start->subtype )
	  rstart = start->u.integer;
    }
    if( args > 2 )
    {
#ifdef AUTO_BIGNUM
      if( length->type == PIKE_T_OBJECT )
	int64_from_bignum( &rlength, length->u.object );
      else
#endif
	if( length->type == PIKE_T_INT && !length->subtype )
	  rlength = length->u.integer;
    }
    if( rlength == 0 )
    {
      pop_n_elems(args);
      push_int(0);
      return;
    }
    debug_malloc_touch( source );

    res = source_make( source, rstart, rlength );

    debug_malloc_touch( res );

    SHUFFLE_DEBUG4("add_source(XX,%d,%d) --> %p\n", THIS,
		  (int)rstart, (int)rlength, res );
    if( !res )
      Pike_error("Failed to convert argument to a source\n");

    if( THIS->current_source )
    {
      THIS->last_source->next = res;
      THIS->last_source = res;
    }
    else
      THIS->current_source = THIS->last_source = res;
    pop_n_elems(args);
    push_int(0);
  }
}

#ifdef Shuffle_event_handler_defined
static void Shuffle_event_handler(int ev) {
  switch(ev) {

#ifdef internal_init_Shuffle_defined
  case PROG_EVENT_INIT: init_Shuffle_struct(); break;

#endif /* internal_init_Shuffle_defined */

#ifdef internal_exit_Shuffle_defined
  case PROG_EVENT_EXIT: exit_Shuffle_struct(); break;

#endif /* internal_exit_Shuffle_defined */
  default: break; 
  }
}

#endif /* Shuffle_event_handler_defined */
/*! @endclass
 */

/*! @class Shuffler
 *!
 *! A data shuffler. An instance of this class handles a list of
 *! @[Shuffle] objects. Each @[Shuffle] object can send data from one
 *! or more sources to a destination in the background.
 *! 
 */


#undef class_Shuffler_defined
#define class_Shuffler_defined
struct program *Shuffler_program=NULL;
static int Shuffler_program_fun_num=-1;

#undef var_backend_Shuffler_defined
#define var_backend_Shuffler_defined

#undef var_throttler_Shuffler_defined
#define var_throttler_Shuffler_defined

#undef var_paused_Shuffler_defined
#define var_paused_Shuffler_defined

#undef var_sources_Shuffler_defined
#define var_sources_Shuffler_defined

#undef THIS
#define THIS ((struct Shuffler_struct *)(Pike_interpreter.frame_pointer->current_storage))

#undef THIS_SHUFFLER
#define THIS_SHUFFLER ((struct Shuffler_struct *)(Pike_interpreter.frame_pointer->current_storage))

#undef OBJ2_SHUFFLER
#define OBJ2_SHUFFLER(o) ((struct Shuffler_struct *)(o->storage+Shuffler_storage_offset))

#undef GET_SHUFFLER_STORAGE
#define GET_SHUFFLER_STORAGE ((struct Shuffler_struct *)(o->storage+Shuffler_storage_offset)
static ptrdiff_t Shuffler_storage_offset;
struct Shuffler_struct {

#ifdef var_backend_Shuffler_defined
  struct object * backend;

#endif /* var_backend_Shuffler_defined */

#ifdef var_throttler_Shuffler_defined
  struct object * throttler;

#endif /* var_throttler_Shuffler_defined */

#ifdef var_paused_Shuffler_defined
#line 749 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
int paused;
#endif /* var_paused_Shuffler_defined */

#ifdef var_sources_Shuffler_defined
  struct array * sources;

#endif /* var_sources_Shuffler_defined */
};
#line 753 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
static void update_sources()
  {
    push_array( THIS->sources );
    debug_malloc_touch( THIS->sources );
    push_int(0);
    f_aggregate(1);
    o_subtract();
    THIS->sources = Pike_sp[-1].u.array;
    debug_malloc_touch( THIS->sources );
    Pike_sp--;
  }
  

  #define f_Shuffler_set_backend_defined
ptrdiff_t f_Shuffler_set_backend_fun_num = 0;
void f_Shuffler_set_backend(INT32 args) {
#line 766 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct object * b;
#line 766 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 1) wrong_number_of_args_error("set_backend",args,1);
#line 766 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(Pike_sp[0-1].type != PIKE_T_OBJECT) SIMPLE_BAD_ARG_ERROR("set_backend",1,"object");
#line 766 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
debug_malloc_pass(b=Pike_sp[0-1].u.object);
/*! @decl void set_backend( Pike.Backend b );
     *! Set the backend that will be used by all @[Shuffle] objects created
     *! from this shuffler.
     *! 
     */
  {
    if( THIS->backend )
      free_object( THIS->backend );
    THIS->backend = b;
    debug_malloc_touch( THIS->backend );
    Pike_sp--;
    push_int(0);
  }

  }
#define f_Shuffler_set_throttler_defined
ptrdiff_t f_Shuffler_set_throttler_fun_num = 0;
void f_Shuffler_set_throttler(INT32 args) {
#line 781 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct object * t;
#line 781 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args > 1) wrong_number_of_args_error("set_throttler",args,1);
if ((args > 0) && 
    ((Pike_sp[0-args].type != PIKE_T_INT) ||
     (Pike_sp[0-args].u.integer))) {
#line 781 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(Pike_sp[0-args].type != PIKE_T_OBJECT) SIMPLE_BAD_ARG_ERROR("set_throttler",1,"object|void");
#line 781 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
debug_malloc_pass(t=Pike_sp[0-args].u.object);
} else t=0;
/*! @decl void set_throttler( Throttler t );
     *! Set the throttler that will be used in all @[Shuffle] objects
     *! created from this shuffler, unless overridden in the
     *! @[Shuffle] objects.
     *! 
     */
  
#line 788 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    if( THIS->throttler )
      free_object( THIS->throttler );
    THIS->throttler = t;
    debug_malloc_touch( THIS->throttler );
    Pike_sp--;
    push_int(0);
  }

  }
#define f_Shuffler_pause_defined
ptrdiff_t f_Shuffler_pause_fun_num = 0;
void f_Shuffler_pause(INT32 args) {
#line 797 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 0) wrong_number_of_args_error("pause",args,0);
/*! @decl void pause();
     *! Pause all @[Shuffle] objects associated with this @[Shuffler]
     *! 
     */
  {
    int i;
    update_sources();
    for( i = 0; i<THIS->sources->size; i++ )
    {
      struct Shuffle_struct *s =
	(struct Shuffle_struct *)THIS->sources->item[i].u.object->storage;
      if( s->state == RUNNING )
	_remove_callbacks( s );
    }
  }

  }
#define f_Shuffler_start_defined
ptrdiff_t f_Shuffler_start_fun_num = 0;
void f_Shuffler_start(INT32 args) {
#line 814 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 0) wrong_number_of_args_error("start",args,0);
/*! @decl void start();
     *! Unpause all @[Shuffle] objects associated with this @[Shuffler]
     *! 
     */
  {
    int i;
    update_sources();
    for( i = 0; i<THIS->sources->size; i++ )
    {
      struct Shuffle_struct *s =
	(struct Shuffle_struct *)THIS->sources->item[i].u.object->storage;
      if( s->state == RUNNING )
	_set_callbacks( s );
    }
  }

  }
#define f_Shuffler_cq____remove_shuffle_defined
ptrdiff_t f_Shuffler_cq____remove_shuffle_fun_num = 0;
void f_Shuffler_cq____remove_shuffle(INT32 args) {
#line 831 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct object * so;
#line 831 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 1) wrong_number_of_args_error("___remove_shuffle",args,1);
#line 831 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(Pike_sp[0-1].type != PIKE_T_OBJECT) SIMPLE_BAD_ARG_ERROR("___remove_shuffle",1,"object");
#line 831 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
debug_malloc_pass(so=Pike_sp[0-1].u.object);
{
    f_aggregate(1);
    push_array( THIS->sources );
    stack_swap();
    o_subtract();
    THIS->sources = Pike_sp[-1].u.array;
    debug_malloc_touch( THIS->sources );
    Pike_sp--;
    push_int(0);
  }

  }
#define f_Shuffler_shuffle_defined
ptrdiff_t f_Shuffler_shuffle_fun_num = 0;
void f_Shuffler_shuffle(INT32 args) {
#line 843 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
struct object * destination;
#line 843 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(args != 1) wrong_number_of_args_error("shuffle",args,1);
#line 843 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
if(Pike_sp[0-1].type != PIKE_T_OBJECT) SIMPLE_BAD_ARG_ERROR("shuffle",1,"object");
#line 843 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
debug_malloc_pass(destination=Pike_sp[0-1].u.object);
/*! @decl Shuffle shuffle( Stdio.File destination );
     *! Create a new @[Shuffle] object.
     *! 
     */
  {
    ref_push_object( Pike_fp->current_object ); /* shuffler */
    if( THIS->throttler )
      ref_push_object( THIS->throttler );
    else
      push_int( 0 );
    if( THIS->backend )
      ref_push_object( THIS->backend );
    else
      push_int( 0 );

    push_object( clone_object( Shuffle_program, 4 ) );
    stack_dup();
    f_aggregate( 1 );
    push_array( THIS->sources );
    stack_swap();
    f_add(2);
    THIS->sources = Pike_sp[-1].u.array;
    debug_malloc_touch( THIS->sources );
    Pike_sp--;
  }

  }

#undef internal_init_Shuffler_defined
#define internal_init_Shuffler_defined

#undef Shuffler_event_handler_defined
#define Shuffler_event_handler_defined
static void init_Shuffler_struct(void)
#line 871 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
{
    THIS->sources = allocate_array(0);
  }

#ifdef Shuffler_event_handler_defined
static void Shuffler_event_handler(int ev) {
  switch(ev) {

#ifdef internal_init_Shuffler_defined
  case PROG_EVENT_INIT: init_Shuffler_struct(); break;

#endif /* internal_init_Shuffler_defined */
  default: break; 
  }
}

#endif /* Shuffler_event_handler_defined */
/*! @endclass
 */

/*! @decl constant INITIAL;
 *! @decl constant RUNNING;
 *! @decl constant PAUSED;
 *! @decl constant DONE;
 *! @decl constant WRITE_ERROR;
 *! @decl constant READ_ERROR;
 *! @decl constant USER_ABORT;
 */

/*! @endmodule
 */

#line 891 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
PIKE_MODULE_INIT
{
  
#ifdef class_Shuffle_defined

#ifdef PROG_SHUFFLE_ID
#line 82 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
  START_NEW_PROGRAM_ID(SHUFFLE);
#else
#line 82 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
  start_new_program();

#endif /* PROG_SHUFFLE_ID */

#ifndef tObjImpl_SHUFFLE

#undef tObjImpl_SHUFFLE
#define tObjImpl_SHUFFLE tObj

#endif /* tObjImpl_SHUFFLE */

#ifdef THIS_SHUFFLE

  Shuffle_storage_offset=ADD_STORAGE(struct Shuffle_struct);

#endif /* THIS_SHUFFLE */

#ifdef var_shuffler_Shuffle_defined
  PIKE_MAP_VARIABLE("shuffler", Shuffle_storage_offset + OFFSETOF(Shuffle_struct, shuffler),
                    tObj, PIKE_T_OBJECT, 0);
#endif /* var_shuffler_Shuffle_defined */

#ifdef var_throttler_Shuffle_defined
  PIKE_MAP_VARIABLE("throttler", Shuffle_storage_offset + OFFSETOF(Shuffle_struct, throttler),
                    tObj, PIKE_T_OBJECT, 0);
#endif /* var_throttler_Shuffle_defined */

#ifdef var_done_callback_Shuffle_defined
  PIKE_MAP_VARIABLE("done_callback", Shuffle_storage_offset + OFFSETOF(Shuffle_struct, done_callback),
                    tMix, PIKE_T_MIXED, 0);
#endif /* var_done_callback_Shuffle_defined */

#ifdef var_request_arg_Shuffle_defined
  PIKE_MAP_VARIABLE("request_arg", Shuffle_storage_offset + OFFSETOF(Shuffle_struct, request_arg),
                    tMix, PIKE_T_MIXED, 0);
#endif /* var_request_arg_Shuffle_defined */

#ifdef Shuffle_event_handler_defined
  pike_set_prog_event_callback(Shuffle_event_handler);

#endif /* Shuffle_event_handler_defined */

#ifdef f_Shuffle_set_throttler_defined
  f_Shuffle_set_throttler_fun_num =
#line 158 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("set_throttler", f_Shuffle_set_throttler, tFunc(tObj,tVoid), 0, OPT_SIDE_EFFECT);

#endif /* f_Shuffle_set_throttler_defined */

#ifdef f_Shuffle_sent_data_defined
  f_Shuffle_sent_data_fun_num =
#line 174 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("sent_data", f_Shuffle_sent_data, tFunc(tNone,"\10\200\0\0\0\177\377\377\377"), 0, OPT_TRY_OPTIMIZE);

#endif /* f_Shuffle_sent_data_defined */

#ifdef f_Shuffle_state_defined
  f_Shuffle_state_fun_num =
#line 185 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("state", f_Shuffle_state, tFunc(tNone,"\10\200\0\0\0\177\377\377\377"), 0, OPT_TRY_OPTIMIZE);

#endif /* f_Shuffle_state_defined */

#ifdef f_Shuffle_set_done_callback_defined
  f_Shuffle_set_done_callback_fun_num =
#line 390 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("set_done_callback", f_Shuffle_set_done_callback, tFunc(tMix,tVoid), 0, OPT_SIDE_EFFECT);

#endif /* f_Shuffle_set_done_callback_defined */

#ifdef f_Shuffle_set_request_arg_defined
  f_Shuffle_set_request_arg_fun_num =
#line 402 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("set_request_arg", f_Shuffle_set_request_arg, tFunc(tMix,tVoid), 0, OPT_SIDE_EFFECT);

#endif /* f_Shuffle_set_request_arg_defined */

#ifdef f_Shuffle_send_more_callback_defined
  f_Shuffle_send_more_callback_fun_num =
#line 534 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("send_more_callback", f_Shuffle_send_more_callback, tFunc("\10\200\0\0\0\177\377\377\377",tVoid), 0, OPT_SIDE_EFFECT);

#endif /* f_Shuffle_send_more_callback_defined */

#ifdef f_Shuffle_write_callback_defined
  f_Shuffle_write_callback_fun_num =
#line 549 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("write_callback", f_Shuffle_write_callback, tFunc(tOr(tMix,tVoid),tVoid), 0, OPT_SIDE_EFFECT);

#endif /* f_Shuffle_write_callback_defined */

#ifdef f_Shuffle_create_defined
  f_Shuffle_create_fun_num =
#line 559 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("create", f_Shuffle_create, tFunc(tObj tObj tMix tMix,tVoid), ID_STATIC, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_Shuffle_create_defined */

#ifdef f_Shuffle_start_defined
  f_Shuffle_start_fun_num =
#line 614 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("start", f_Shuffle_start, tFunc(tNone,tVoid), 0, OPT_SIDE_EFFECT);

#endif /* f_Shuffle_start_defined */

#ifdef f_Shuffle_pause_defined
  f_Shuffle_pause_fun_num =
#line 628 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("pause", f_Shuffle_pause, tFunc(tNone,tVoid), 0, OPT_SIDE_EFFECT);

#endif /* f_Shuffle_pause_defined */

#ifdef f_Shuffle_stop_defined
  f_Shuffle_stop_fun_num =
#line 640 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("stop", f_Shuffle_stop, tFunc(tNone,tVoid), 0, OPT_SIDE_EFFECT);

#endif /* f_Shuffle_stop_defined */

#ifdef f_Shuffle_add_source_defined
  f_Shuffle_add_source_fun_num =
#line 651 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("add_source", f_Shuffle_add_source, tFunc(tMix tOr(tMix,tVoid) tOr(tMix,tVoid),tVoid), 0, OPT_SIDE_EFFECT);

#endif /* f_Shuffle_add_source_defined */
#line 82 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
  Shuffle_program=end_program();
#line 82 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
  Shuffle_program_fun_num=add_program_constant("Shuffle",Shuffle_program,0);

#endif /* class_Shuffle_defined */

#ifdef class_Shuffler_defined

#ifdef PROG_SHUFFLER_ID
#line 744 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
  START_NEW_PROGRAM_ID(SHUFFLER);
#else
#line 744 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
  start_new_program();

#endif /* PROG_SHUFFLER_ID */

#ifndef tObjImpl_SHUFFLER

#undef tObjImpl_SHUFFLER
#define tObjImpl_SHUFFLER tObj

#endif /* tObjImpl_SHUFFLER */

#ifdef THIS_SHUFFLER

  Shuffler_storage_offset=ADD_STORAGE(struct Shuffler_struct);

#endif /* THIS_SHUFFLER */

#ifdef var_backend_Shuffler_defined
  PIKE_MAP_VARIABLE("backend", Shuffler_storage_offset + OFFSETOF(Shuffler_struct, backend),
                    tObj, PIKE_T_OBJECT, 0);
#endif /* var_backend_Shuffler_defined */

#ifdef var_throttler_Shuffler_defined
  PIKE_MAP_VARIABLE("throttler", Shuffler_storage_offset + OFFSETOF(Shuffler_struct, throttler),
                    tObj, PIKE_T_OBJECT, 0);
#endif /* var_throttler_Shuffler_defined */

#ifdef var_sources_Shuffler_defined
  PIKE_MAP_VARIABLE("sources", Shuffler_storage_offset + OFFSETOF(Shuffler_struct, sources),
                    tArray, PIKE_T_ARRAY, 0);
#endif /* var_sources_Shuffler_defined */

#ifdef Shuffler_event_handler_defined
  pike_set_prog_event_callback(Shuffler_event_handler);

#endif /* Shuffler_event_handler_defined */

#ifdef f_Shuffler_set_backend_defined
  f_Shuffler_set_backend_fun_num =
#line 766 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("set_backend", f_Shuffler_set_backend, tFunc(tObj,tVoid), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_Shuffler_set_backend_defined */

#ifdef f_Shuffler_set_throttler_defined
  f_Shuffler_set_throttler_fun_num =
#line 781 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("set_throttler", f_Shuffler_set_throttler, tFunc(tOr(tObj,tVoid),tVoid), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_Shuffler_set_throttler_defined */

#ifdef f_Shuffler_pause_defined
  f_Shuffler_pause_fun_num =
#line 797 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("pause", f_Shuffler_pause, tFunc(tNone,tVoid), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_Shuffler_pause_defined */

#ifdef f_Shuffler_start_defined
  f_Shuffler_start_fun_num =
#line 814 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("start", f_Shuffler_start, tFunc(tNone,tVoid), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_Shuffler_start_defined */

#ifdef f_Shuffler_cq____remove_shuffle_defined
  f_Shuffler_cq____remove_shuffle_fun_num =
#line 831 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("___remove_shuffle", f_Shuffler_cq____remove_shuffle, tFunc(tObj,tVoid), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_Shuffler_cq____remove_shuffle_defined */

#ifdef f_Shuffler_shuffle_defined
  f_Shuffler_shuffle_fun_num =
#line 843 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    ADD_FUNCTION2("shuffle", f_Shuffler_shuffle, tFunc(tObj,tObj), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_Shuffler_shuffle_defined */
#line 744 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
  Shuffler_program=end_program();
#line 744 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
  Shuffler_program_fun_num=add_program_constant("Shuffler",Shuffler_program,0);

#endif /* class_Shuffler_defined */
#line 893 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
;
  sources_init();
  add_integer_constant( "INITIAL", INITIAL, 0 );
  add_integer_constant( "RUNNING", RUNNING, 0 );
  add_integer_constant( "PAUSED", PAUSED, 0 );
  add_integer_constant( "DONE", DONE, 0 );
  add_integer_constant( "WRITE_ERROR", WRITE_ERROR, 0 );
  add_integer_constant( "READ_ERROR", READ_ERROR, 0 );
  add_integer_constant( "USER_ABORT", USER_ABORT, 0 );
}

PIKE_MODULE_EXIT
{
  
#ifdef class_Shuffle_defined
  if(Shuffle_program) {
#line 82 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    free_program(Shuffle_program);
    Shuffle_program=0;
  }

#endif /* class_Shuffle_defined */

#ifdef class_Shuffler_defined
  if(Shuffler_program) {
#line 744 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
    free_program(Shuffler_program);
    Shuffler_program=0;
  }

#endif /* class_Shuffler_defined */
#line 906 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/post_modules/Shuffler/Shuffler.cmod"
;
  sources_exit();
}

