docs: public EventImpl publishEvent(Event event, boolean async) {
          EventImpl eventImpl = (EventImpl) event;
          eventImpl.setReadOnly(true);
          EventImpl currentEvent = (EventImpl) CurrentEvent.get();
          if (null != currentEvent) {
              eventImpl.setParent(currentEvent);
          }
  
          // Attempt to get the Topic object and cached TopicData but fallback
          // to the topic name if the Topic object wasn't populated
          Topic topic = eventImpl.getTopicObject();
          String topicName = topic != null ? topic.getName() : eventImpl.getTopic();
          TopicData topicData = topicCache.getTopicData(topic, topicName);
          eventImpl.setTopicData(topicData);
  
          // Required Java 2 Security check
          checkTopicPublishPermission(topicName);
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) {
              Tr.event(tc, "Publishing Event", topicName);
          }
  
          // Obtain list of matching handlers: returned list of handlers
          // must be thread safe!
          List<HandlerHolder> holders = topicData.getEventHandlers();
          ExecutorService executor = topicData.getExecutorService();
  
          if (async) {
              int i = 0;
              // Handle asynchronous events.
              Future<?>[] futures = new Future<?>[holders.size()];
              for (HandlerHolder holder : holders) {
                  holder.addEvent(eventImpl);
                  futures[i++] = queueWorkRequest(holder, executor);
              }
              eventImpl.setFutures(futures);
          } else {
              // fire synchronous events
              for (HandlerHolder holder : holders) {
                  holder.fireSynchronousEvent(eventImpl);
              }
          }
  
          return eventImpl;
      }