All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.ihmc.pubsub.impl.intraprocess.IntraProcessDomainImpl Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
/*
 * Copyright 2024 Florida Institute for Human and Machine Cognition (IHMC)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */
package us.ihmc.pubsub.impl.intraprocess;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;

import us.ihmc.pubsub.TopicDataType;
import us.ihmc.pubsub.attributes.ParticipantProfile;
import us.ihmc.pubsub.attributes.PublisherAttributes;
import us.ihmc.pubsub.attributes.SubscriberAttributes;
import us.ihmc.pubsub.common.DiscoveryStatus;
import us.ihmc.pubsub.common.LogLevel;
import us.ihmc.pubsub.common.MatchingInfo.MatchingStatus;
import us.ihmc.pubsub.common.SampleInfo;
import us.ihmc.pubsub.participant.ParticipantListener;
import us.ihmc.pubsub.publisher.PublisherListener;
import us.ihmc.pubsub.subscriber.Subscriber;
import us.ihmc.pubsub.subscriber.SubscriberListener;

@Deprecated
class IntraProcessDomainImpl
{
//   private final Executor threadPool = Executors.newCachedThreadPool(); // give threads a name
   private final Executor threadPool = Executors.newSingleThreadExecutor(new ThreadFactory()
   {
      private final AtomicInteger threadNumber = new AtomicInteger(1);

      @Override
      public Thread newThread(Runnable r)
      {
         Thread t = new Thread(r, "IntraProcessDomainImpl-thread-" + threadNumber.getAndIncrement());

         if (!t.isDaemon())
            t.setDaemon(true);
         if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);

         return t;
      }
   });

   private final ReentrantLock domainLock = new ReentrantLock();

   private final List participants = new ArrayList<>();
   private final HashMap> subscribers = new HashMap<>();
   private final HashMap> publishers = new HashMap<>();

   private LogLevel logLevel;
   
   public IntraProcessDomainImpl(int domainID, LogLevel logLevel)
   {
      this.logLevel = logLevel;
   }

   private void matchParticipants(Consumer exec)
   {
      for (IntraProcessParticipant participant : participants)
      {
         if (logLevel == LogLevel.INFO)
         {
            IntraProcessLog.info(this, "Notifying matched participant " + participant);
         }
         threadPool.execute(() -> exec.accept(participant));
      }
   }

   private void matchSubscribers(PublisherAttributes publisherToMatch, Consumer exec)
   {
      List topicSubscribers = subscribers.get(publisherToMatch.getTopicName());
      if (topicSubscribers != null)
      {
         for (IntraProcessSubscriber subscriber : topicSubscribers)
         {
            if (IntraProcessUtil.subscriberPublisherMatches(subscriber.getAttributes(), publisherToMatch))
            {
               if (logLevel == LogLevel.INFO)
               {
                  IntraProcessLog.info(this, "Notifying matched subscriber " + subscriber);
               }
               threadPool.execute(() -> exec.accept(subscriber));
            }
         }
      }
   }

   private void matchPublishers(SubscriberAttributes subscriberToMatch, Consumer exec)
   {
      List topicPublishers = publishers.get(subscriberToMatch.getTopicName());
      if (topicPublishers != null)
      {
         for (IntraProcessPublisher publisher : topicPublishers)
         {
            if (IntraProcessUtil.subscriberPublisherMatches(subscriberToMatch, publisher.getAttributes()))
            {
               if (logLevel == LogLevel.INFO)
               {
                  IntraProcessLog.info(this, "Notifying matched publisher " + publisher);
               }
               threadPool.execute(() -> exec.accept(publisher));
            }
         }
      }
   }

   IntraProcessParticipant createParticipant(ParticipantProfile attributes, ParticipantListener listener)
   {
      domainLock.lock();
      try
      {
         IntraProcessParticipant participant = new IntraProcessParticipant(this, attributes, listener);

         if (logLevel == LogLevel.INFO)
         {
            IntraProcessLog.info(this, "Adding participant " + participant);
         }
         matchParticipants((participantToNotify) -> participantToNotify.notifyParticipantListener(participant, DiscoveryStatus.DISCOVERED_RTPSPARTICIPANT));

         if (logLevel == LogLevel.INFO)
            IntraProcessLog.info(this, "Notifying self of existing participants");
         matchParticipants((participantOnline) -> participant.notifyParticipantListener(participantOnline, DiscoveryStatus.DISCOVERED_RTPSPARTICIPANT));

         participants.add(participant);
         return participant;
      } finally
      {
         domainLock.unlock();
      }
   }

   boolean removeParticipant(IntraProcessParticipant participant)
   {
      domainLock.lock();
      try
      {
         if (logLevel == LogLevel.INFO)
         {
            IntraProcessLog.info(this, "Removing participant " + participant);
         }
         if (participants.remove(participant))
         {
            for (IntraProcessSubscriber subscriber : participant.getSubscribers())
            {
               removeSubscriber(subscriber);
            }
            for (IntraProcessPublisher publisher : participant.getPublishers())
            {
               removePublisher(publisher);
            }
            participant.destroy();
            matchParticipants((participantToNotify) -> participantToNotify.notifyParticipantListener(participant, DiscoveryStatus.REMOVED_RTPSPARTICIPANT));
            return true;
         }
         else
         {
            return false;
         }
      } finally
      {
         domainLock.unlock();
      }
   }

   Subscriber createSubscriber(IntraProcessParticipant participant, SubscriberAttributes attr, SubscriberListener listener) throws IOException
   {
      domainLock.lock();
      try
      {
         IntraProcessSubscriber subscriber = participant.createSubscriber(this, attr, listener);

         String topicName = attr.getTopicName();
         List topicSubscribers = subscribers.get(topicName);
         if (topicSubscribers == null)
         {
            if (logLevel == LogLevel.INFO)
            {
               IntraProcessLog.info(this, "Creating new subscriber list for topic " + topicName);
            }
            topicSubscribers = new ArrayList<>();
            subscribers.put(topicName, topicSubscribers);
         }

         if (logLevel == LogLevel.INFO)
         {
            IntraProcessLog.info(this, "Adding subscriber " + subscriber);
         }
         topicSubscribers.add(subscriber);

         if (logLevel == LogLevel.INFO)
            IntraProcessLog.info(this, "Notifying subscribers discovery listeners");
         matchParticipants((participantToNotify) -> participantToNotify.notifySubscriberDiscoveryListener(subscriber));
         if (logLevel == LogLevel.INFO)
            IntraProcessLog.info(this, "Notifying publisher listeners");
         matchPublishers(subscriber.getAttributes(), (publisher) -> publisher.notifyPublisherListener(subscriber, MatchingStatus.MATCHED_MATCHING));

         if (logLevel == LogLevel.INFO)
            IntraProcessLog.info(this, "Notifying self listener of existing publishers");
         matchPublishers(subscriber.getAttributes(), (publisher) -> subscriber.notifySubscriberListener(publisher, MatchingStatus.MATCHED_MATCHING));

         return subscriber;
      } finally
      {
         domainLock.unlock();
      }
   }

   boolean removeSubscriber(IntraProcessSubscriber subscriber)
   {
      domainLock.lock();
      try
      {
         String topicName = subscriber.getAttributes().getTopicName();
         List topicSubscribers = subscribers.get(topicName);
         if (topicSubscribers == null)
         {
            if (logLevel == LogLevel.WARNING)
               IntraProcessLog.warn(this, "Subscriber is not part of this domain");

            return false;
         }

         if (logLevel == LogLevel.INFO)
         {
            IntraProcessLog.info(this, "Removing subscriber " + subscriber);
         }
         if (topicSubscribers.remove(subscriber))
         {
            subscriber.getParticipant().unregister(subscriber);
            if (logLevel == LogLevel.INFO)
               IntraProcessLog.info(this, "Notifying publisher listeners");
            matchPublishers(subscriber.getAttributes(), (publisher) -> publisher.notifyPublisherListener(subscriber, MatchingStatus.REMOVED_MATCHING));
            subscriber.destroy();
         }
         else
         {
            if (logLevel == LogLevel.WARNING)
               IntraProcessLog.warn(this, "No subscriber matched in this domain");
            return false;
         }
         return true;
      } finally
      {
         domainLock.unlock();

      }
   }

   IntraProcessPublisher createPublisher(IntraProcessParticipant participant, PublisherAttributes attr, PublisherListener listener)
         throws IOException
   {
      domainLock.lock();
      try
      {
         IntraProcessPublisher publisher = participant.createPublisher(this, attr, listener);
         String topicName = attr.getTopicName();
         List topicPublishers = publishers.get(topicName);
         if (topicPublishers == null)
         {
            if (logLevel == LogLevel.INFO)
            {
               IntraProcessLog.info(this, "Creating new publisher list for topic " + topicName);
            }
            topicPublishers = new ArrayList<>();
            publishers.put(topicName, topicPublishers);
         }

         if (logLevel == LogLevel.INFO)
         {
            IntraProcessLog.info(this, "Adding publisher in topic: " + publisher.getAttributes().getTopicName() + " : " + publisher);
         }
         topicPublishers.add(publisher);
         if (logLevel == LogLevel.INFO)
            IntraProcessLog.info(this, "Notifying publisher discovery listeners");
         matchParticipants((participantToNotify) -> participantToNotify.notifyPublisherDiscoveryListener(publisher));
         if (logLevel == LogLevel.INFO)
            IntraProcessLog.info(this, "Notifying subscriber listeners");
         matchSubscribers(publisher.getAttributes(), (subscriber) -> subscriber.notifySubscriberListener(publisher, MatchingStatus.MATCHED_MATCHING));

         if (logLevel == LogLevel.INFO)
            IntraProcessLog.info(this, "Notify self listener of existing subscribers");
         matchSubscribers(publisher.getAttributes(), (subscriber) -> publisher.notifyPublisherListener(subscriber, MatchingStatus.MATCHED_MATCHING));

         return publisher;
      } finally
      {
         domainLock.unlock();
      }
   }

   boolean removePublisher(IntraProcessPublisher publisher)
   {
      domainLock.lock();
      try
      {
         String topicName = publisher.getAttributes().getTopicName();
         List topicSubscribers = publishers.get(topicName);
         if (topicSubscribers == null)
         {
            if (logLevel == LogLevel.WARNING)
               IntraProcessLog.warn(this, "No publisher matched in domain");
            return false;
         }

         if (logLevel == LogLevel.INFO)
         {
            IntraProcessLog.info(this, "Removing publisher " + topicName);
         }
         if (topicSubscribers.remove(publisher))
         {
            publisher.getParticipant().unregister(publisher);
            if (logLevel == LogLevel.INFO)
               IntraProcessLog.info(this, "Notifying subscriber listeners");
            matchSubscribers(publisher.getAttributes(), (subscriber) -> subscriber.notifySubscriberListener(publisher, MatchingStatus.REMOVED_MATCHING));
            publisher.destroy();
         }
         else
         {

            if (logLevel == LogLevel.WARNING)
               IntraProcessLog.warn(this, "No subscriber matched in domain");

            return false;
         }
         return true;
      } finally
      {
         domainLock.unlock();
      }
   }

    void write(PublisherAttributes attr, TopicDataType type, T data, SampleInfo info) throws IOException
   {
      domainLock.lock();
      
      try
      {
         List topicSubscribers = subscribers.get(attr.getTopicName());
         if (topicSubscribers != null)
         {
            for (IntraProcessSubscriber subscriber : topicSubscribers)
            {
               if (IntraProcessUtil.subscriberPublisherMatches(subscriber.getAttributes(), attr))
               {
                  if (logLevel == LogLevel.INFO)
                  {
//                     IntraProcessLog.info(this, "Publishing " + data + " to " + subscriber);
                  }

                  T newData = type.createData();
                  if (!newData.getClass().isAssignableFrom(data.getClass()))
                  {
                     throw new IOException("Expected message of type " + newData.getClass().getName() + "; got " + data.getClass().getName());
                  }

                  type.copy(data, newData);

                  SampleInfo newInfo = new SampleInfo();
                  newInfo.set(info);
                  threadPool.execute(() -> subscriber.putNextData(newData, newInfo));
               }
            }
         }
      } finally
      {
         domainLock.unlock();
      }
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy