class_docstr: Writes given dataset into FFCV format (.beton).
  Supports indexable objects (e.g., PyTorch Datasets) and webdataset.
  
  Parameters
  ----------
  fname: str
      File name to store dataset in FFCV format (.beton)
  fields : Mapping[str, Field]
      Map from keys to Field's (order matters!)
  page_size : int
      Page size used internally
  num_workers : int
      Number of processes to use
code: def _write_common(
      self, num_samples, queue_content, work_fn, extra_worker_args
  ):
      self.num_samples = num_samples
  
      self.prepare()
      allocation_list = []
  
      # Makes a memmap to the metadata for the samples
  
      # We publish all the work that has to be done into a queue
      workqueue: Queue = Queue()
      for todo in queue_content:
          workqueue.put(todo)
  
      # This will contain all the memory allocations each worker
      # produced. This will go at the end of the file
      allocations_queue: Queue = Queue()
  
      # We add a token for each worker to warn them that there
      # is no more work to be done
      for _ in range(self.num_workers):
          workqueue.put(None)
  
      # Define counters we need to orchestrate the workers
      done_number = Value(ctypes.c_uint64, 0)
      allocator = MemoryAllocator(
          self.fname, self.data_region_start, self.page_size
      )
  
      # Arguments that have to be passed to the workers
      worker_args = (
          workqueue,
          self.metadata_sm,
          self.metadata_type,
          self.fields,
          allocator,
          done_number,
          allocations_queue,
          *extra_worker_args,
      )
  
      # Create the workers
      processes = [
          Process(target=work_fn, args=worker_args)
          for _ in range(self.num_workers)
      ]
      # start the workers
      for p in processes:
          p.start()
      # Wait for all the workers to be done
  
      # Display progress
      progress = tqdm(total=self.num_samples)
      previous = 0
      while previous != self.num_samples:
          val = done_number.value
          diff = val - previous
          if diff > 0:
              progress.update(diff)
          previous = val
          sleep(0.1)
      progress.close()
  
      # Wait for all the workers to be done and get their allocations
      for p in processes:
          content = allocations_queue.get()
          allocation_list.extend(content)
  
      self.finalize(allocation_list)
      self.metadata_sm.close()
      self.metadata_sm.unlink()
  
imports: from functools import partial
  from typing import Callable, List, Mapping
  from os import SEEK_END, path
  import numpy
  from time import sleep
  import ctypes
  from multiprocessing import shared_memory, cpu_count, Queue, Process, Value
  from tqdm import tqdm
  from tqdm.contrib.concurrent import thread_map
  from .utils import chunks, is_power_of_2
  from .fields.base import Field
  from .memory_allocator import MemoryAllocator
  from .types import TYPE_ID_HANDLER, get_metadata_type, HeaderType, FieldDescType, CURRENT_VERSION, ALLOC_TABLE_TYPE
label_desc: Use image node_id 3 for calling the DatasetWriter obj's underlying member method code with example usage: obj._write_common(num_samples, queue_content, work_fn, extra_worker_args) without return types