/*
  CoreLinux++ 
  Copyright (C) 2000 CoreLinux Consortium
  
   The CoreLinux++ Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The CoreLinux++ Library Library is distributed in the hope that it will 
   be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  
*/   

/** \example examp21c.cpp

   This example is the client for showing the use of the SemaphoreCommon 
   cross process shared groups.
   
   What it does is start up, open up the Semaphore group that should be
   available via the server process. When ready it prompts the user
   for input strings to pump across the shared memory segment.   
*/                   

#if   !defined(__EX21_HPP)
#include <ex21.hpp>
#endif


#include <iostream>
#include <exception>





//
// In module function prototypes
//

int   main( int argc, char *argv[] );

//
// General Functions 
//

using namespace corelinux;
using namespace std;

void  handleAssertion( AssertionCref );
void  handleException( ExceptionCref );

//
// Type declarations
//


//
// Main entry point
//


int   main( int argc, char *argv[] )
{

   cout << endl;

   //
   // Practice graceful exception management
   //


   try
   {
      bool                    keepGoing(true);

      MutexSemaphoreGroupPtr  aControlGroup( NULLPTR );
      AbstractSemaphore       *aServerSem( NULLPTR );
      AbstractSemaphore       *aClientSem( NULLPTR );
      MemoryStoragePtr        aTransfer( NULLPTR );
      TransferBlockPtr        aBlock( NULLPTR );


      try
      {
         aControlGroup = new MutexSemaphoreGroup
            (
               0,theSemName,0,FAIL_IF_NOTEXISTS
            );

         aServerSem = aControlGroup->createSemaphore
            (
               theServerSemId,
               FAIL_IF_NOTEXISTS
            );

         aClientSem = aControlGroup->createLockedSemaphore
            (
               theClientSemId,
               FAIL_IF_NOTEXISTS
            );

         aTransfer = Memory::createStorage
                     (
                        theMemName,
                        0,
                        FAIL_IF_NOTEXISTS,
                        0
                     );

         aBlock = TransferBlockPtr( *aTransfer );

         cout << "Client process ready to go." << endl;

         do
         {
            aServerSem->lockWithWait();

            //
            // get input from user
            // Signal the server
            //

            cout  << "Child has control" << endl;
            cout  << "Enter a string to send, or 'exit' to finish: ";
            cin   >> aBlock->theData;
            aBlock->theEntrySize = strlen(aBlock->theData);

            //
            // Determine if we should exit
            //

            if( strcmp(aBlock->theData,"exit") == 0 )
            {
               aBlock->theEntrySize = 0;
               keepGoing = false;
            }

            if( aBlock->theEntrySize == 0 )
            {
            }
            else
            {
               ;  // do nothing
            }

            aClientSem->release();


         } while( keepGoing == true );

         aServerSem->release();
         aControlGroup->destroySemaphore( aServerSem );
         aServerSem = NULLPTR;
         aControlGroup->destroySemaphore( aClientSem );
         aClientSem = NULLPTR;
         Memory::destroyStorage( aTransfer );
         aTransfer = NULLPTR;

      }
      catch( SemaphoreExceptionRef aSemExcp )
      {
         cerr << "Semaphore Exception Received" << endl;
         handleException(aSemExcp);
      }
      catch( AssertionRef aAssert )
      {
         handleAssertion(aAssert);
      }
      catch( ExceptionRef aException )
      {
         handleException(aException);
      }
      catch(...)
      {
         cerr << "Unknown exception received" << endl;
      }

      cout << "Client process exiting." << endl;

      if( aTransfer != NULLPTR )
      {
         Memory::destroyStorage( aTransfer );
         aTransfer = NULLPTR;
      }
      else
      {
         ;  // do nothing
      }

      if( aControlGroup != NULLPTR )
      {
         if( aServerSem != NULLPTR )
         {
            aControlGroup->destroySemaphore( aServerSem );
         }
         else
         {
            ;  // do nothing
         }

         if( aClientSem != NULLPTR )
         {
            aControlGroup->destroySemaphore( aClientSem );
         }
         else
         {
            ;  // do nothing
         }

         delete aControlGroup;
      }
   }

   catch( NullPointerException aException )
   {
      cerr  << "Received NullPointerException!" << endl;
      handleException(aException);
   }
   catch( AssertionRef aAssert )
   {
      handleAssertion(aAssert);
   }
   catch( ExceptionRef aException )
   {
      handleException(aException);
   }
   catch( std::exception & e )
   {
      cerr  << e.what() << endl;
   }
   catch( ... )
   {
      cerr  << "Unknown exception." << endl;
   }

   return 0;               
}

//
// Some utility functions
//

//
// Error handlers
//

void  handleAssertion( AssertionCref aAssert )
{
   cerr << aAssert.getFile() << ":" << aAssert.getLine() << ":" << 
      "Assertion: ";

   if( aAssert.getType() == Assertion::NEVERGETHERE )
   {
      cerr << "NEVER_GET_HERE";
   }
   else
   {
      if( aAssert.getType() == Assertion::REQUIRE )
      {
         cerr  << "REQUIRE";
      }
      else if( aAssert.getType() == Assertion::ENSURE )
      {
         cerr  << "ENSURE";
      }
      else if( aAssert.getType() == Assertion::CHECK )
      {
         cerr  << "CHECK";
      }
      else 
      {
         cerr  << "ASSERT";
      }
      cerr << "( " << aAssert.getWhy() << " )";
   }

   cerr << endl;
}

void  handleException( ExceptionCref aExcp )
{
   cerr << aExcp.getFile() << ":" << aExcp.getLine() << ":" <<
      "Exception: " << aExcp.getWhy() << endl;
}

/*
   Common rcs information do not modify
   $Author: prudhomm $
   $Revision: 1.5 $
   $Date: 2000/08/31 22:49:01 $
   $Locker:  $
*/


