! @brief Write all collected data to flash.
        
        This routine ensures that chip erase is only used once if either the auto mode or chip
        erase mode are used. As an example, if two regions are to be written to and True was
        passed to the constructor for chip_erase (or if the session option was set), then only
        the first region will actually use chip erase. The second region will be forced to use
        sector erase. This will not result in extra erasing, as sector erase always verifies whether
        the sectors are already erased. This will, of course, also work correctly if the flash
        algorithm for the first region doesn't actually erase the entire chip (all regions).
        
        After calling this method, the loader instance can be reused to program more data.

def commit(self):
        """! @brief Write all collected data to flash.
        
        This routine ensures that chip erase is only used once if either the auto mode or chip
        erase mode are used. As an example, if two regions are to be written to and True was
        passed to the constructor for chip_erase (or if the session option was set), then only
        the first region will actually use chip erase. The second region will be forced to use
        sector erase. This will not result in extra erasing, as sector erase always verifies whether
        the sectors are already erased. This will, of course, also work correctly if the flash
        algorithm for the first region doesn't actually erase the entire chip (all regions).
        
        After calling this method, the loader instance can be reused to program more data.
        """
        didChipErase = False
        perfList = []
        
        # Iterate over builders we've created and program the data.
        for builder in sorted(self._builders.values(), key=lambda v: v.flash_start):
            # Determine this builder's portion of total progress.
            self._current_progress_fraction = builder.buffered_data_size / self._total_data_size
            
            # Program the data.
            chipErase = self._chip_erase if not didChipErase else False
            perf = builder.program(chip_erase=chipErase,
                                    progress_cb=self._progress_cb,
                                    smart_flash=self._smart_flash,
                                    fast_verify=self._trust_crc,
                                    keep_unwritten=self._keep_unwritten)
            perfList.append(perf)
            didChipErase = True
            
            self._progress_offset += self._current_progress_fraction

        # Report programming statistics.
        self._log_performance(perfList)
        
        # Clear state to allow reuse.
        self._reset_state()