docs: def process_buffer(self, i_block, receive_buffer):
          """Blocking function to process the received heaps.
          This is run in an executor.
          """
          self._log.info("Worker thread processing block %i", i_block)
          time_overall0 = time.time()
          time_unpack = 0.0
          time_write = 0.0
          for i_heap, heap in enumerate(receive_buffer.result()):
              # Skip and log any incomplete heaps.
              if isinstance(heap, spead2.recv.IncompleteHeap):
                  self._log.info("Dropped incomplete heap %i", heap.cnt + 1)
                  continue
  
              # Update the item group from this heap.
              items = self._item_group.update(heap)
  
              # Get the time and channel indices from the heap index.
              i_chan = i_heap // self._num_buffer_times
              i_time = i_heap % self._num_buffer_times
  
              if 'correlator_output_data' in items:
                  vis_data = items['correlator_output_data'].value['VIS']
                  if self._block is None:
                      num_baselines = vis_data.shape[0]
                      num_pols = vis_data[0].shape[0]
                      self._block = numpy.zeros((self._num_buffer_times,
                                                 self._num_streams,
                                                 num_baselines),
                                                dtype=('c8', num_pols))
                      self._block[:, :, :] = 0  # To make the copies faster.
  
                  # Unpack data from the heap into the block to be processed.
                  time_unpack0 = time.time()
                  self._block[i_time, i_chan, :] = vis_data
                  time_unpack += time.time() - time_unpack0
  
                  # Check the data for debugging!
                  val = self._block[i_time, i_chan, -1][-1].real
                  self._log.debug("Data: %.3f", val)
  
          if self._block is not None:
              # Process the buffered data here.
              if self._config['process_data']:
                  pass
  
              # Write the buffered data to storage.
              if self._config['write_data']:
                  time_write0 = time.time()
                  with open(self._config['filename'], 'ab') as f:
                      # Don't use pickle, it's really slow (even protocol 4)!
                      numpy.save(f, self._block, allow_pickle=False)
                  time_write += time.time() - time_write0
  
          # Report time taken.
          time_overall = time.time() - time_overall0
          self._log.info("Total processing time: %.1f ms", 1000 * time_overall)
          self._log.info("Unpack was %.1f %%", 100 * time_unpack / time_overall)
          self._log.info("Write was %.1f %%", 100 * time_write / time_overall)
          if time_unpack != 0.0:
              self._log.info("Memory speed %.1f MB/s",
                             (self._block.nbytes * 1e-6) / time_unpack)
          if time_write != 0.0:
              self._log.info("Write speed %.1f MB/s",
                             (self._block.nbytes * 1e-6) / time_write)