public function start_progress($description, $max = self::INDETERMINATE,
            $parentcount = 1) {
        if ($max != self::INDETERMINATE && $max < 0) {
            throw new \coding_exception(
                    'start_progress() max value cannot be negative');
        }
        if ($parentcount < 1) {
            throw new \coding_exception(
                    'start_progress() parent progress count must be at least 1');
        }
        if (!empty($this->descriptions)) {
            $prevmax = end($this->maxes);
            if ($prevmax !== self::INDETERMINATE) {
                $prevcurrent = end($this->currents);
                if ($prevcurrent + $parentcount > $prevmax) {
                    throw new \coding_exception(
                            'start_progress() parent progress would exceed max');
                }
            }
        } else {
            if ($parentcount != 1) {
                throw new \coding_exception(
                        'start_progress() progress count must be 1 when no parent');
            }
        }
        $this->descriptions[] = $description;
        $this->maxes[] = $max;
        $this->currents[] = 0;
        $this->parentcounts[] = $parentcount;
        $this->update_progress();
    }