code: public int allocate(final String label, final int typeId, final Consumer<MutableDirectBuffer> keyFunc)
      {
          final int counterId = nextCounterId();
          checkCountersCapacity(counterId);
  
          final int recordOffset = metaDataOffset(counterId);
          checkMetaDataCapacity(recordOffset);
  
          try
          {
              metaDataBuffer.putInt(recordOffset + TYPE_ID_OFFSET, typeId);
              keyFunc.accept(new UnsafeBuffer(metaDataBuffer, recordOffset + KEY_OFFSET, MAX_KEY_LENGTH));
              metaDataBuffer.putLong(recordOffset + FREE_FOR_REUSE_DEADLINE_OFFSET, NOT_FREE_TO_REUSE);
              putLabel(recordOffset, label);
  
              metaDataBuffer.putIntOrdered(recordOffset, RECORD_ALLOCATED);
          }
          catch (final Exception ex)
          {
              freeList.pushInt(counterId);
              LangUtil.rethrowUnchecked(ex);
          }
  
          return counterId;
      }
docs: Allocate a new counter with a given label.
  <p>
  The key function will be called with a buffer with the exact length of available key space
  in the record for the user to store what they want for the key. No offset is required.
  
  @param label   to describe the counter.
  @param typeId  for the type of counter.
  @param keyFunc for setting the key value for the counter.
  @return the id allocated for the counter.