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.
#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
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:
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; }