Subscribers

Here are some examples of a subscriber that works with the publishers given above. They basically loop forever, reading updates to the button object, but each uses a different method of waiting for data.

Using a blocking read()

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char *argv[])
{
   int fd;
   char buf[256];
   int num_bytes;

   fd = open( "/pps/example/button?wait,delta", O_RDONLY );
   if ( fd < 0 )
   {
      perror ("Couldn't open /pps/example/button");
      return EXIT_FAILURE;
   }

   /* Loop, echoing the attributes of the button. */
   while (1)
   {
      num_bytes = read( fd, buf, sizeof(buf) );
      if (num_bytes > 0)
      {
        write (STDOUT_FILENO, buf, num_bytes);
      }
   }

   return EXIT_SUCCESS;
}

Note the following:

If both sample publishers are running, the output from this subscriber looks something like this:

@button
color::red
pub1::536
pub2::878
state::on

@button
color::green
pub2::879

@button
state::off
pub1::537

@button
color::red
pub2::880

@button
state::on
pub1::538

The output includes only the updates made by each publisher; the first time the subscriber reads the data, it gets all of the attributes, because their values are all new to this subscriber.

If we don't specify the delta option, the output includes all of the object's attributes whenever the subscriber reads the file, whether their values changed or not:

@button
color::green
pub1::654
pub2::1073
state::on

@button
color::red
pub1::654
pub2::1074
state::on

@button
color::green
pub1::654
pub2::1075
state::on

@button
color::green
pub1::655
pub2::1075
state::off

Using ionotify()

This subscriber uses the default nonblocking reads with ionotify():

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/neutrino.h>
#include <sys/netmgr.h>
#include <sys/siginfo.h>
#include <sys/iomgr.h>

int main(int argc, char *argv[])
{
   int fd;
   char buf[256];
   int num_bytes;
   int chid, coid, ret;
   struct sigevent my_event;
   struct _pulse pulse;

   fd = open( "/pps/example/button?delta", O_RDONLY );
   if ( fd < 0 )
   {
      perror ("Couldn't open /pps/example/button");
      return EXIT_FAILURE;
   }

   /* We need a channel to ourself. */
   chid = ChannelCreate (0);
   if ( chid < 0 )
   {
      perror ("Couldn't create a channel");
      return EXIT_FAILURE;
   }

   coid = ConnectAttach (0, 0, chid, _NTO_SIDE_CHANNEL, 0);
   if ( coid < 0 )
   {
      perror ("Couldn't create a connection");
      return EXIT_FAILURE;
   }

   /* Set up a sigevent to notify us of PPS data. */
   SIGEV_PULSE_INIT( &my_event, coid, SIGEV_PULSE_PRIO_INHERIT,
                     _PULSE_CODE_MINAVAIL, 0);
   
   /* Loop, echoing the attributes of the button. */
   while (1)
   {
      ret = ionotify( fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &my_event);
      while ((ret != -1) && (ret & _NOTIFY_COND_INPUT))
      {
         /* Data is available right now. Read the attributes and print
            them on stdout. */
         num_bytes = read( fd, buf, sizeof(buf) );
         if (num_bytes > 0)
         {
           write (STDOUT_FILENO, buf, num_bytes);
         }

         ret = ionotify( fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &my_event);
      }

      if (ret == -1)
      {
         perror ("ionotify() failed");
         return EXIT_FAILURE;
      }

      /* Block until PPS informs us that there's new data. */
      ret = MsgReceivePulse_r( chid, &pulse, sizeof(pulse), NULL );
      if ( ret < 0 )
      {
          printf ("MsgReceivePulse_r(): %s\n", strerror (ret));
          return EXIT_FAILURE;
      }
   }

  return EXIT_SUCCESS;
}

Note the following:

Using select()

This subscriber uses nonblocking reads with select(), which requires less setup than the ionotify() version:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/select.h>

int main(int argc, char *argv[])
{
   int fd;
   char buf[256];
   int num_bytes;
   int ret;
   fd_set readfds;
   struct timeval timeout;

   fd = open( "/pps/example/button?delta", O_RDONLY );
   if ( fd < 0 )
   {
      perror ("Couldn't open /pps/example/button");
      return EXIT_FAILURE;
   }

   timeout.tv_sec = 2;
   timeout.tv_usec = 0;
   
   /* Loop, echoing the attributes of the button. */
   while (1)
   {
      FD_ZERO( &readfds );
      FD_SET( fd, &readfds );

      switch ( ret = select( fd + 1, &readfds, NULL, NULL, &timeout ) )
      {
         case -1:
            perror( "select()" );
            return EXIT_FAILURE;
         case  0:
            printf( "select() timed out.\n" );
            break;
         default:
            if( FD_ISSET( fd, &readfds ) )
            {
               /* Read the attributes and print them on stdout. */
               num_bytes = read( fd, buf, sizeof(buf) );
               if (num_bytes > 0)
               {
                  write (STDOUT_FILENO, buf, num_bytes);
               }
            }
      }
   }

   return EXIT_SUCCESS;
}