src/core/unix-system-thread.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 3790 2c655e67f7b1
permissions -rw-r--r--
Added tag ns-3.5 for changeset c975274c9707
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2008 INRIA
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Author: Mathieu Lacage <mathieu.lacage.inria.fr>
    19  */
    20 
    21 #include <pthread.h>
    22 #include <string.h>
    23 #include <signal.h>
    24 #include "fatal-error.h"
    25 #include "system-thread.h"
    26 #include "log.h"
    27 
    28 NS_LOG_COMPONENT_DEFINE ("SystemThread");
    29 
    30 namespace ns3 {
    31 
    32 //
    33 // Private implementation class for the SystemThread class.  The deal is
    34 // that we export the SystemThread class to the user.  The header just 
    35 // declares a class and its members.  There is a forward declaration for
    36 // a private implementation class there and a member declaration.  Thus
    37 // there is no knowledge of the implementation in the exported header.
    38 //
    39 // We provide an implementation class for each operating system.  This is
    40 // the Unix implementation of the SystemThread.
    41 //
    42 // In order to use the SystemThread, you will include "system-thread.h" and
    43 // get the implementation by linking unix-system-thread.cc (if you are running
    44 // a Posix system).
    45 //
    46 class SystemThreadImpl
    47 {
    48 public:
    49   SystemThreadImpl (Callback<void> callback);
    50 
    51   void Start (void);
    52   void Join (void);
    53   void Shutdown (void);
    54   bool Break (void);
    55 
    56 private:
    57   static void *DoRun (void *arg);
    58   Callback<void> m_callback;
    59   pthread_t m_thread;
    60   bool m_break;
    61   void *    m_ret;
    62 };
    63 
    64 SystemThreadImpl::SystemThreadImpl (Callback<void> callback)
    65   : m_callback (callback)
    66 {
    67   NS_LOG_FUNCTION_NOARGS ();
    68   // Make sure we have a SIGALRM handler which does not terminate
    69   // our process.
    70   struct sigaction act;
    71   act.sa_flags = 0;
    72   sigemptyset (&act.sa_mask);
    73   act.sa_handler = SIG_IGN;
    74   sigaction (SIGALRM, &act, 0);
    75 }
    76 
    77   void
    78 SystemThreadImpl::Start (void)
    79 {
    80   NS_LOG_FUNCTION_NOARGS ();
    81 
    82   int rc = pthread_create (&m_thread, NULL, &SystemThreadImpl::DoRun,
    83     (void *)this);
    84 
    85   if (rc) 
    86     {
    87       NS_FATAL_ERROR ("pthread_create failed: " << rc << "=\"" << 
    88         strerror(rc) << "\".");
    89     }
    90 }
    91 
    92   void 
    93 SystemThreadImpl::Join (void)
    94 {
    95   NS_LOG_FUNCTION_NOARGS ();
    96 
    97   void *thread_return;
    98   int rc = pthread_join (m_thread, &thread_return);
    99   if (rc) 
   100     {
   101       NS_FATAL_ERROR ("pthread_join failed: " << rc << "=\"" << 
   102         strerror(rc) << "\".");
   103     }
   104 }
   105 
   106   void 
   107 SystemThreadImpl::Shutdown (void)
   108 {
   109   NS_LOG_FUNCTION_NOARGS ();
   110 
   111   m_break = true;
   112 
   113   // send a SIGALRM signal on the target thread to make sure that it
   114   // will unblock.
   115   pthread_kill (m_thread, SIGALRM);
   116 }
   117 
   118   bool
   119 SystemThreadImpl::Break (void)
   120 {
   121   NS_LOG_FUNCTION_NOARGS ();
   122 
   123   return m_break;
   124 }
   125 
   126   void *
   127 SystemThreadImpl::DoRun (void *arg)
   128 {
   129   NS_LOG_FUNCTION_NOARGS ();
   130 
   131   SystemThreadImpl *self = static_cast<SystemThreadImpl *> (arg);
   132   self->m_callback ();
   133 
   134   return 0;
   135 }
   136 
   137 //
   138 // Remember that we just export the delcaration of the SystemThread class to
   139 // the user.  There is no code to implement the SystemThread methods.  We
   140 // have to do that here.  We just vector the calls to our implementation 
   141 // class above.
   142 //
   143 SystemThread::SystemThread (Callback<void> callback) 
   144   : m_impl (new SystemThreadImpl (callback)),
   145     m_count (1)
   146 {
   147   NS_LOG_FUNCTION_NOARGS ();
   148 }
   149   
   150 SystemThread::~SystemThread() 
   151 {
   152   NS_LOG_FUNCTION_NOARGS ();
   153   delete m_impl;
   154 }
   155   
   156   void 
   157 SystemThread::Start (void)
   158 {
   159   NS_LOG_FUNCTION_NOARGS ();
   160   m_impl->Start ();
   161 }
   162   
   163   void 
   164 SystemThread::Join (void) 
   165 {
   166   NS_LOG_FUNCTION_NOARGS ();
   167   m_impl->Join ();
   168 }  
   169 
   170   void 
   171 SystemThread::Shutdown (void) 
   172 {
   173   NS_LOG_FUNCTION_NOARGS ();
   174   m_impl->Shutdown ();
   175 }  
   176 
   177   bool 
   178 SystemThread::Break (void) 
   179 {
   180   NS_LOG_FUNCTION_NOARGS ();
   181   return m_impl->Break ();
   182 }  
   183 
   184 } // namespace ns3