GNU Radio 3.7.0 C++ API
ice_application_base.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /* 
00003  * Copyright 2012 Free Software Foundation, Inc.
00004  *
00005  * This file is part of GNU Radio
00006  * 
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 3, or (at your option)
00010  * any later version.
00011  *
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with GNU Radio; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #ifndef ICE_APPLICATION_BASE_H
00024 #define ICE_APPLICATION_BASE_H
00025 
00026 #ifdef HAVE_WINDOWS_H
00027 #include <winsock2.h>
00028 #include <sys/time.h>
00029 #endif
00030 
00031 #include <gnuradio/api.h>
00032 #include <gnuradio/prefs.h>
00033 #include <Ice/Ice.h>
00034 #include <boost/thread.hpp>
00035 #include <boost/thread/mutex.hpp>
00036 #include <stdio.h>
00037 #include <iostream>
00038 #include <set>
00039 #include <string>
00040 #include <stdio.h>
00041 
00042 namespace {
00043   static const unsigned int ICEAPPLICATION_ACTIVATION_TIMEOUT_MS(600);
00044 };
00045 
00046 class GR_RUNTIME_API ice_application_common : public Ice::Application 
00047 {
00048  public:
00049   template<typename TserverBase, typename TserverClass> friend class ice_application_base;
00050   static boost::shared_ptr<ice_application_common> Instance();
00051   ~ice_application_common() {;}
00052   static int d_reacquire_attributes;
00053   
00054  protected:
00055   static bool d_main_called;
00056   static bool d_have_ice_config;
00057   static std::string d_endpointStr;
00058   static boost::shared_ptr<boost::thread> d_thread;
00059   ice_application_common() {;}
00060   int run(int, char*[]);
00061 };
00062 
00063 template<typename TserverBase, typename TserverClass>
00064 class ice_application_base
00065 {
00066 public:
00067   boost::shared_ptr<ice_application_common> d_application;
00068   ice_application_base(TserverClass* _this);
00069   ~ice_application_base() {;}
00070     
00071   static TserverBase* i();
00072   static const std::vector<std::string> endpoints();
00073     
00074 protected:
00075   bool have_ice_config() { return d_application->d_have_ice_config; }
00076   void set_endpoint(const std::string& endpoint) { d_application->d_endpointStr = endpoint;}
00077   
00078   //this one is the key... overwrite in templated/inherited variants
00079   virtual TserverBase* i_impl() = 0;
00080 
00081   //tools for the i_impl... 
00082   //tell it when it has to resync with the communicator
00083   virtual bool reacquire_sync();
00084   virtual void sync_reacquire();
00085 
00086   static TserverClass* d_this;
00087     
00088   int d_reacquire;
00089   //static int d_reacquire_attributes;
00090     
00091 private:
00092   void starticeexample();
00093     
00094   bool application_started();
00095     
00096   int run(int, char*[]);
00097     
00098   static void kickoff();
00099 };
00100 
00101 template<typename TserverBase, typename TserverClass>
00102 TserverClass* ice_application_base<TserverBase, TserverClass>::d_this(0);
00103 
00104 //template<typename TserverBase, typename TserverClass>
00105 //int ice_application_base<TserverBase, TserverClass>::d_reacquire_attributes(0);
00106 
00107 template<typename TserverBase, typename TserverClass>
00108 ice_application_base<TserverBase, TserverClass>::ice_application_base(TserverClass* _this)
00109   : d_reacquire(0) 
00110 {
00111   //d_reacquire_attributes = 0;
00112   d_this = _this;
00113   d_application = ice_application_common::Instance();
00114 }
00115 
00116 template<typename TserverBase, typename TserverClass>
00117 void ice_application_base<TserverBase, TserverClass>::starticeexample()
00118 {
00119   char* argv[2];
00120   argv[0] = (char*)"";
00121 
00122   std::string conffile = gr::prefs::singleton()->get_string("ControlPort", "config", "");
00123 
00124   if(conffile.size() > 0) {
00125     std::stringstream iceconf;
00126     ice_application_common::d_have_ice_config = true; 
00127     ice_application_common::d_main_called = true;
00128     iceconf << conffile;
00129     d_application->main(0, argv, iceconf.str().c_str());
00130   }
00131   else {
00132     ice_application_common::d_have_ice_config = false; 
00133     ice_application_common::d_main_called = true;
00134     d_application->main(0, argv);
00135   }
00136 }
00137 
00138 template<typename TserverBase, typename TserverClass>
00139 void ice_application_base<TserverBase, TserverClass>::kickoff()
00140 {
00141   static bool run_once = false;
00142   
00143   //if(!d_this->application_started()) {
00144   if(!run_once) {
00145     ++d_this->d_application->d_reacquire_attributes;
00146     
00147     ice_application_common::d_thread = boost::shared_ptr<boost::thread>
00148       (new boost::thread(boost::bind(&ice_application_base::starticeexample, d_this)));
00149   
00150     ::timespec timer_ts, rem_ts;
00151     timer_ts.tv_sec = 0; timer_ts.tv_nsec = ICEAPPLICATION_ACTIVATION_TIMEOUT_MS*1000;
00152   
00153     int iter = 0;
00154     while(!d_this->application_started()) {
00155       #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
00156           ::Sleep(timer_ts.tv_nsec / 1000000);
00157           #else
00158       ::nanosleep(&timer_ts, &rem_ts);
00159           #endif
00160       if(!d_this->application_started())
00161         std::cout << "@";
00162       if(iter++ > 100) {
00163         std::cout << "ice_application_base::kickoff(), timeout waiting to get communicator() d_application->main() might have failed?!" << std::endl;;
00164         break;
00165       }
00166     }
00167     
00168     run_once = true;
00169   }
00170   
00171   return;
00172 }
00173 
00174 
00175 template<typename TserverBase, typename TserverClass>
00176 bool ice_application_base<TserverBase, TserverClass>::reacquire_sync()
00177 {
00178   return (d_this->d_reacquire != d_application->d_reacquire_attributes);
00179 }
00180 
00181 template<typename TserverBase, typename TserverClass>
00182 void ice_application_base<TserverBase, TserverClass>::sync_reacquire()
00183 {
00184   d_this->d_reacquire = d_application->d_reacquire_attributes;
00185 }
00186 
00187 
00188 template<typename TserverBase, typename TserverClass>
00189 const std::vector<std::string> ice_application_base<TserverBase, TserverClass>::endpoints()
00190 {
00191   std::vector<std::string> ep; ep.push_back(d_this->d_application->d_endpointStr); return ep;
00192 }
00193 
00194 template<typename TserverBase, typename TserverClass>
00195 TserverBase* ice_application_base<TserverBase, TserverClass>::i()
00196 {
00197   //printf("indacall\n");
00198   
00199   assert(d_this != 0);
00200   if(!d_this->application_started()) {
00201     //printf("anotherkickoff\n");
00202     kickoff();
00203   }
00204   //printf("donekickedoff\n");
00205   
00206   /*else if(!d_proxy) {
00207     d_proxy = d_this->i_impl();
00208     assert(d_proxy != 0);
00209     }*/
00210 
00211   return d_this->i_impl(); 
00212 }
00213 
00214 /*template<typename TserverBase, typename TserverClass>
00215   int ice_application_base<TserverBase, TserverClass>::run(int argc, char* argv[]) {
00216   int implreturn(run_impl(argc, argv));
00217   ice_application_base<TserverBase, TserverClass>::communicator()->waitForShutdown();
00218   return implreturn;
00219   }*/
00220 
00221 template<typename TserverBase, typename TImplClass>
00222 bool ice_application_base<TserverBase, TImplClass>::application_started()
00223 {
00224   return ice_application_base<TserverBase, TImplClass>::d_this->d_application->communicator();
00225 }
00226 
00227 /*template<typename TserverBase, typename TImplClass>
00228 int ice_application_base<TserverBase, TImplClass>::run_impl(int argc, char* argv[]) { return EXIT_SUCCESS; }
00229 */
00230 
00231 #endif