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