Beispiel #1
0
static struct cl_attr *
new_cl_attr(char *cl_name)
{
	struct cl_attr *class, **class_ptr;

	if (cl_handle == -1) {
		cl_handle = ar_create(MALSIZ, sizeof (struct cl_attr),
		    "package class");
		if (cl_handle == -1) {
			progerr(gettext(ERR_MEMORY));
			return (NULL);
		}
	}

	class_ptr = (struct cl_attr **)ar_next_avail(cl_handle);

	if (class_ptr == NULL || *class_ptr == NULL) {
		progerr(gettext(ERR_MEMORY));
		return (NULL);
	}

	class = *class_ptr;

	strcpy(class->name, cl_name);
	class->inst_script = NULL;
	class->rem_script = NULL;
	class->src_verify = s_verify(cl_name);
	class->dst_verify = d_verify(cl_name);
	class->relpath_2_CAS = s_pathtype(cl_name);

	return (class);
}
Beispiel #2
0
  /* protected slot */
  void
  int_range_steps_holder::
before_dtor( QObject * p_attached_object_about_to_be_destroyed)
{
    QWidget * const
        p_attached_widget_about_to_be_destroyed =
            qobject_cast< QWidget * >( p_attached_object_about_to_be_destroyed);
    d_assert( p_attached_widget_about_to_be_destroyed);
    d_verify( 1 == attached_widgets_.removeAll( p_attached_widget_about_to_be_destroyed));
}
Beispiel #3
0
  void
  int_range_steps_holder::
detach( QAbstractSlider * p_slider)
{
    d_assert( p_slider);
    d_assert( is_valid( ));
    d_assert( attached_widgets_.contains( p_slider));

    d_verify( disconnect( p_slider, SIGNAL( valueChanged( int)), this, SLOT( set_value( int))));
    d_verify( disconnect( p_slider, SIGNAL( destroyed( QObject *)), this, SLOT( before_dtor( QObject *))));
    d_verify( 1 == attached_widgets_.removeAll( p_slider));

    d_assert( ! attached_widgets_.contains( p_slider));
    d_assert( is_valid( ));
}
Beispiel #4
0
  /* ctor */
  double_slide_holder::
double_slide_holder
 (  QObject *   p_parent
  , value_type  outer_init  // = 0.0
  , value_type  outer_lo    // = -1.0
  , value_type  outer_hi    // = +1.0
 )
  : holder_base_type( p_parent)
  , p_inner_holder_ ( 0)
  , outer_lo_       ( 0)
  , inner_to_outer_ ( 0)
  , outer_to_inner_ ( 0)
{
    setup_conversions( outer_lo, outer_hi);

    // Now that conversions are set up, create the inner holder.
    // Should we use the global lo/hi limits, or the calculated limits? We'll use the
    // calculated limits for now.
    p_inner_holder_ =
        new inner_holder_type
             (  this
              , convert_outer_to_inner( outer_init)
              , convert_outer_to_inner( outer_lo)
              , convert_outer_to_inner( outer_hi)
             );
    d_assert( p_inner_holder_);

    // Relay all the signals from the inner holder.
    d_verify( connect(
        p_inner_holder_, SIGNAL( has_changed( )),
        this, SLOT( intercept__has_changed( ))
    ));
    d_verify( connect(
        p_inner_holder_, SIGNAL( has_changed( int)),
        this, SLOT( intercept__has_changed( int))
    ));
    d_verify( connect(
        p_inner_holder_, SIGNAL( has_changed__range( int, int)),
        this, SLOT( intercept__has_changed__range( int, int))
    ));
    d_verify( connect(
        p_inner_holder_, SIGNAL( has_changed__steps( int, int)),
        this, SLOT( intercept__has_changed__steps( int, int))
    ));

    // Should always be true when outside class methods.
    d_assert( is_valid( ));
}
Beispiel #5
0
  void
  solver_type::
fix_severely_out_of_bounds_sheet( sheet_type & trg_sheet)
  //
  // This is like a sheet-transforming functor, and should probably be integrated into
  // the solvers so it can calculate off-thread (and maybe even in parallel).
{
    // We need a way to do this in a worker thread (and ideally parallel) without
    // incrementing the generation count. So this either needs to be integrated into
    // the solvers, or we need to have a general way to queue worker-thread instructions.

    value_type const normal_min = -1;
    value_type const normal_max = +1;
    value_type const normal_mid =  0;

    // We don't flatten the sheet unless it gets out of this range (except in the
    // special case where the sheet is completely flat):
    value_type const out_of_bounds_min = -100;
    value_type const out_of_bounds_max = +100;

    // After we're done none of the sheet values should be outside this range:
    value_type const back_in_bounds_min = -50;
    value_type const back_in_bounds_max = +50;

    value_type min_value = 0;
    value_type max_value = 0;
    d_verify( trg_sheet.get_min_max_values( min_value, max_value));
    d_assert( min_value <= max_value);

    // If the sheet is flat ..
    if ( min_value == max_value ) {
        // If the flat value is outside the normal range ..
        if ( (min_value < normal_min) || (max_value > normal_max) ) {
            trg_sheet.fill_sheet( normal_mid);
        }
    } else
    if ( min_value < out_of_bounds_min ) {
        trg_sheet.normalize(
            back_in_bounds_min,
            std::max( normal_mid, std::min( back_in_bounds_max, max_value)));
    } else
    if ( max_value > out_of_bounds_max ) {
        trg_sheet.normalize(
            std::min( normal_mid, std::max( back_in_bounds_min, min_value)),
            back_in_bounds_max);
    }
}
Beispiel #6
0
/*
 * Create a list of all classes involved in this installation as well as
 * their attributes.
 */
int
setlist(struct cl_attr ***plist, char *slist)
{
	struct cl_attr	**list, *struct_ptr;
	char	*pt;
	int	n;
	int	i;
	int	sn = -1;

	/* Initialize the environment scanners. */
	(void) s_verify(NULL);
	(void) d_verify(NULL);
	(void) s_pathtype(NULL);

	n = 0;

	/*
	 * This looks like a serious memory leak, however pkgmk depends on
	 * this creating a second list and forgetting any prior ones. The
	 * pkgmk utility does a reasonable job of keeping track of a prior
	 * list constructed from the prototype file using addlist() above.
	 * Perhaps this should be reviewed later, but I do not believe this
	 * to be a problem from what I've seen. - JST
	 */
	cl_handle = -1;		/* forget other lists */

	/* Isolate the first token. */
	pt = strtok(slist, " \t\n");
	while (pt) {
		if (sn == -1 && strcmp(pt, "none") == 0)
			sn = n;

		/* Add new class to list. */
		if ((struct_ptr = new_cl_attr(pt)) == NULL)
			quit(99);

		/* Next token. */
		n++;
		pt = strtok(NULL, " \t\n");
		if (pt && sn != -1)
			if (strcmp(pt, "none") == 0)
				pt = strtok(NULL, " \t\n");
	}
	/*
	 * According to the ABI, if there is a class "none", it will be
	 * the first class to be installed.  This insures that iff there
	 * is a class "none", it will be the first to be installed.
	 * If there is no class "none", nothing happens!
	 */
	new_order = 0;

	/* Get the head of the array. */
	list = (struct cl_attr **)ar_get_head(cl_handle);

	if (sn > 0) {
		struct_ptr = list[sn];
		for (i = sn; i > 0; i--)
			list[i] = list[i - 1];
		list[0] = struct_ptr;
		new_order++;	/* the order is different now */
	}

	/* Point the passed pointer to the head of the list. */
	*plist = list;

	return (n);
}
Beispiel #7
0
  /* main method */
  void
  solver_type::
calc_next
 (  input_params_type const &  input_params
  , sheet_params_type const &  sheet_params
 )
  // Instead of dealing with sheet_type this could start with these src/trg objects:
  //   stride_range< src_iter_type, 1 >  src_range
  //   stride_range< trg_iter_type, 1 >  trg_range
  // See swap_xy( range_xy) -> range_yx
{
    // Initialize the output params. We will set them as we go along.
    output_params_.reset( );

    sheet_type const &  src_sheet    = sheet_params.ref_src_sheet( );
    sheet_type       &  trg_sheet    = sheet_params.ref_trg_sheet( );
    sheet_type       &  extra_sheet  = sheet_params.ref_extra_sheet( );

    // Interpret input_params and sheet_params as intuitive choices.
    bool const  is_multi_pass               = input_params.has_extra_passes( ) && ! input_params.are_extra_passes_disabled( );
    bool const  is_one_pass                 = ! is_multi_pass;
    bool const  is_in_place_requested       = sheet_params.are_src_trg_sheets_same( );
    bool const  is_in_place_possible        = input_params.is_technique__ortho_interleave( );
    bool const  is_extra_pre_sized          = sheet_params.is_extra_sheet_sized( );
    bool const  is_history_vital            = input_params.is_saving_history_worth_sizing_extra( );
    bool const  is_history_nice             = is_history_vital || input_params.is_saving_history_worth_extra_copy( );
    bool const  is_extra_vital_for_solve    = is_multi_pass && ! is_in_place_possible; /* or is_in_place_requested and not possible */
    bool const  is_extra_vital_for_history  = is_multi_pass || is_in_place_requested;
    bool const  is_extra_vital              = is_extra_vital_for_solve || (is_history_vital && is_extra_vital_for_history);
    bool const  is_extra_nice               = is_extra_vital || (is_history_nice && is_extra_vital_for_history);
    bool const  is_extra_used               = is_extra_vital || (is_extra_nice && is_extra_pre_sized);

    // The two sheets must be different (unless technique == e_ortho_interleave).
    // We could make in_place work for e_simultaneous_2d too (but not for e_wave_with_damping)
    // by using extra_sheet like this (one pass):
    //   copy src -> extra
    //   solve extra -> trg
    // For two passes:
    //   solve src -> extra
    //   solve extra -> trg
    // Three passes:
    //   copy src -> extra
    //   solve extra -> trg
    //   solve trg -> extra
    //   solve extra -> trg
    // In this scenario, extra_sheet always ends up with history.
    d_assert( implies( is_in_place_requested, is_in_place_possible));

    if ( is_extra_vital && ! is_extra_pre_sized ) {
        // We need an extra trg sheet. Make sure it's properly sized.
        d_verify( sheet_params.maybe_size_extra_sheet( ));
        output_params_.set__was_extra_sized( );
    }

    if ( is_extra_used ) {
        // Even if extra_sheet wasn't pre-sized, it's sized now.
        d_assert( sheet_params.is_extra_sheet_sized( ));
        output_params_.set__was_extra_used( );
    } else
    if ( input_params.is_extra_sheet_to_be_reset_if_not_used( ) ) {
        extra_sheet.reset( );
    }

    // If we are solving the wave equation using the extra sheet we have to set up history.
    //
    // We need the following assumtion because we are testing is_odd( extra_pass_count):
    //   d_assert( extra_pass_count >= 0)
    // This is always true because size_type is unsigned.
    d_static_assert( boost::is_unsigned< size_type >::value);
    if ( is_multi_pass && input_params.is_technique__wave_with_damping( ) ) {
        d_assert( is_extra_used);
        if ( is_early_exit( ) ) return;

        // If we are wave solving we need to setup the extra sheet with values so we get
        // the history right. Remember with waves we have a kludge where trg_sheet also
        // holds the src-values from one generation back.
        if ( util::is_odd( input_params.get_extra_pass_count( )) ) {
            // If extra_pass_count is odd the solves will look like:
            //   src -> extra  -- first set (extra <- trg) so history is right
            //   extra -> trg  -- first set (trg <- src) so history is right
            //   trg -> extra  -- ok
            //   extra -> trg  -- ok
            extra_sheet = trg_sheet;
            trg_sheet   = src_sheet;
        } else {
            // If extra_pass_count is even (and not zero) the solves look like this:
            //   src -> trg           -- ok
            //   trg -> extra  -- first set (extra <- src) so history is right
            //   extra -> trg  -- ok
            //   trg -> extra  -- ok
            //   extra -> trg  -- ok
            extra_sheet = src_sheet;
        }
    }

    // Solve repeatedly if extra solve passes are requested.
    // Alternatively solve to trg_sheet and extra_sheet, assuming extra_sheet is available.
    sheet_type const * p_src_sheet = & src_sheet;
    for ( size_type
            countdown = is_multi_pass ? input_params.get_extra_pass_count( ) : 0
          ; countdown > 0
          ; -- countdown )
    {
        if ( is_early_exit( ) ) return;
        output_params_.inc_solve_count( );

        bool const    is_this_pass_targeting_extra  = is_extra_used && util::is_odd( countdown);
        sheet_type &  trg_sheet_this_pass           = is_this_pass_targeting_extra ? extra_sheet : trg_sheet;
        calc_next_pass
         (  input_params.get_technique( )
          , input_params.get_method( )
          , input_params.is_method_parallel( )
          , input_params.get_damping( )
          , input_params.get_rate_x( )
          , input_params.get_rate_y( )
          , *p_src_sheet
          , trg_sheet_this_pass
         );
        p_src_sheet = & trg_sheet_this_pass;
    }

    // We're about to do the last solve. The 2nd-to-last solution is in *p_src_sheet, which is:
    //   src_sheet if this is not just the last solve, but also the only solve.
    //   extra_sheet if we were using extra_sheet in the loop above.
    //   trg_sheet if in_place solving is possible and history is not required.
    if ( is_one_pass ) {
        d_assert( (& src_sheet) == p_src_sheet);
        if ( is_in_place_requested ) {
            // There is one unusual case where we have to copy src_sheet to preserve history.
            if ( is_history_nice && is_extra_used ) {
                if ( is_early_exit( ) ) return;
                extra_sheet = src_sheet;
                output_params_.set__is_last_solve_saved_in_extra( );
            } else {
                /* we are doing one in-place solve */
                /* history is not saved */
            }
        } else {
            output_params_.set__is_last_solve_saved_in_src( );
        }
    } else
    if ( is_extra_used ) {
        // Multi-pass and we had the extra sheet available. In that case we always solve into it.
        // In this case history is always returned in extra_sheet, even if not requested.
        d_assert( (& extra_sheet) == p_src_sheet);
        output_params_.set__is_last_solve_saved_in_extra( );
    } else {
        // Multi-pass and we don't have extra_sheet. We must be solving in-place.
        d_assert( (& trg_sheet) == p_src_sheet);
        d_assert( is_in_place_possible);
        d_assert( ! is_history_vital);
        d_assert( ! (is_history_nice && is_extra_pre_sized));
        /* history is not saved */
    }

    // Do the last-pass solve.
    // For the last pass we always solve into the trg_sheet.
    if ( is_early_exit( ) ) return;
    output_params_.inc_solve_count( );
    calc_next_pass
     (  input_params.get_technique( )
      , input_params.get_method( )
      , input_params.is_method_parallel( )
      , input_params.get_damping( )
      , input_params.get_rate_x( )
      , input_params.get_rate_y( )
      , *p_src_sheet
      , trg_sheet
     );
}
Beispiel #8
0
  void
  control_type::
calc_next
 (  sheet_type const &  src_sheet
  , sheet_type       &  trg_sheet
  , sheet_type       &  extra_sheet
  , bool                are_extra_passes_disabled
)
{
    // Runs in the master thread.
    // The worker thread may not even be created yet.
    d_assert( QThread::currentThread( ) != p_worker_);

    // We should not be processing this message after we have exited.
    if ( is_going_down( ) ) {
        d_assert( false);
        return;
    }

    // We will be busy until we process the "finish" message from the worker thread.
    d_assert( not_busy( ));
    is_busy_ = true;

    // If p_worker_ is zero then we still have to create the worker thread object.
    if ( 0 == p_worker_ ) {
        // Create the thread.
        // We give the worker-thread object no parent (zero pointer) so that signals sent between
        // the master and worker threads are queued instead of dispatched.
        // The ctor for the worker thread runs in the master thread, during creation below.
        // And that ctor starts the worker thread and waits for it to settle.
        p_worker_ = new worker_thread_type( 0);

        // Worker is now running.
        d_assert( p_worker_ && p_worker_->isRunning( ));

        // The parent serves these purposes:
        //   It auto-deletes the object at the end of its life.
        //   When you send a message to an object, Qt has to decide in which thread the message should run.
        //     If the target object has a parent, we use that thread that owns the target object.
        //     If the target object has no parent, we use p_trg->thread( ), which is initially the thread
        //       where the target was created. But we set it below.
        //
        // Since we want messages to p_worker_ to process in that thread, we have to create p_worker_ with
        // no parent (or set it to zero later) and then set the thread.
        //
        // Instead of setting the thread, we could try setting the worker-thread object to be its own parent.
        // It'd look like this:
        //   p_worker_->setParent( p_worker_);
        // This compiles and runs, tho it's not clear what it means for auto-delete.
        // And this doesn't work, even if you follow it with:
        //   p_worker_->moveToThread( p_worker_);
        // The messages to p_worker_ still get dispatched in the master thread.

        // Right now worker_->thread( ) is this (master) thread. And the parent is not set.
        d_assert( p_worker_->thread( ) == QThread::currentThread( ));
        d_assert( p_worker_->parent( ) == 0);

        // Change the thread. You MUST do this from the thread that currently owns the object (this master thread).
        // This will let the signal/slot mechanism work across threads.
        p_worker_->moveToThread( p_worker_);
        // This does not set the parent, so auto-delete is disabled. The worker thread does not delete itself
        // after we call p_worker_->quit( ).
        d_assert( p_worker_->parent( ) == 0);
        // Now messages sent to p_worker_ from the master thread are queued and processed in the worker thread.

        // The worker thread is now awaiting instructions.
        // We use the following 2 async connections, plus ->quit( ), to control it.

        // This is a Qt::QueuedConnection. It is sent from the master and processed in the worker thread.
        // The target (p_worker_ in this case) determines where the message is processed.
          d_verify(
        connect(
            p_worker_, SIGNAL( start__master_to_worker( )),
            p_worker_, SLOT( run__in_worker_thread( )))
          );

        // This is a Qt::QueuedConnection. It is sent from the worker to the master thread.
          d_verify(
        connect(
            p_worker_, SIGNAL( finished__worker_to_master( double)),
            this, SLOT( finished__from_worker_thread( double)))
          );
    }