src/core/system-thread.h
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 3791 cf62138bd445
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
#ifndef SYSTEM_THREAD_H
craigdo@3425
    22
#define SYSTEM_THREAD_H
craigdo@3425
    23
craigdo@3425
    24
#include "callback.h"
craigdo@3425
    25
craigdo@3425
    26
namespace ns3 { 
craigdo@3425
    27
craigdo@3425
    28
class SystemThreadImpl;
craigdo@3425
    29
craigdo@3425
    30
/**
craigdo@3425
    31
 * @brief A class which provides a relatively platform-independent thread
craigdo@3425
    32
 * primitive.
craigdo@3425
    33
 *
craigdo@3425
    34
 * This class allows for creation of multiple threads of execution in a
craigdo@3425
    35
 * process.  The exact implementation of the thread functionality is 
craigdo@3425
    36
 * operating system dependent, but typically in ns-3 one is using an 
craigdo@3425
    37
 * environment in which Posix Threads are supported (either navively or
craigdo@3425
    38
 * in the case of Windows via Cygwin's implementation of pthreads on the 
craigdo@3425
    39
 * Win32 API.  In either case we expect that these will be kernel-level
craigdo@3425
    40
 * threads and therefore a system with multiple CPUs will see truly concurrent 
craigdo@3425
    41
 * execution.
craigdo@3425
    42
 *
craigdo@3425
    43
 * Synchronization between threads is provided via the SystemMutex class.
craigdo@3425
    44
 */
craigdo@3425
    45
class SystemThread 
craigdo@3425
    46
{
craigdo@3425
    47
public:
craigdo@3425
    48
  /**
craigdo@3425
    49
   * @brief Create a SystemThread object.
craigdo@3425
    50
   *
craigdo@3425
    51
   * A system thread object is not created running.  A thread of execution
craigdo@3425
    52
   * must be explicitly started by calling the Start method.  When the 
craigdo@3425
    53
   * Start method is called, it will spawn a thread of execution and cause
craigdo@3425
    54
   * that thread to call out into the callback function provided here as
craigdo@3425
    55
   * a parameter.
craigdo@3425
    56
   *
craigdo@3425
    57
   * Like all ns-3 callbacks, the provided callback may refer to a function
craigdo@3425
    58
   * or a method of an object depending on how the MakeCallback function is
craigdo@3425
    59
   * used.
craigdo@3425
    60
   *
craigdo@3425
    61
   * The most common use is expected to be creating a thread of execution in
craigdo@3425
    62
   * a method.  In this case you would use code similar to,
craigdo@3425
    63
   *
craigdo@3425
    64
   *   MyClass myObject;
craigdo@3425
    65
   *   Ptr<SystemThread> st = Create<SystemThread> (
craigdo@3425
    66
   *     MakeCallback (&MyClass::MyMethod, &myObject));
craigdo@3425
    67
   *   st->Start ();
craigdo@3425
    68
   *
craigdo@3425
    69
   * The SystemThread is passed a callback that calls out to the function
craigdo@3425
    70
   * MyClass::MyMethod.  When this function is called, it is called as an
craigdo@3425
    71
   * object method on the myObject object.  Essentially what you are doing
craigdo@3425
    72
   * is asking the SystemThread to call object->MyMethod () in a new thread
craigdo@3425
    73
   * of execution.
craigdo@3425
    74
   *
craigdo@3425
    75
   * Remember that if you are invoking a callback on an object that is
craigdo@3425
    76
   * managed by a smart pointer, you need to call PeekPointer.
craigdo@3425
    77
   *
craigdo@3425
    78
   *   Ptr<MyClass> myPtr = Create<MyClass> ();
craigdo@3425
    79
   *   Ptr<SystemThread> st = Create<SystemThread> (
craigdo@3425
    80
   *     MakeCallback (&MyClass::MyMethod, PeekPointer (myPtr)));
craigdo@3425
    81
   *   st->Start ();
craigdo@3425
    82
   *
craigdo@3425
    83
   * Just like any thread, you can synchronize with its termination.  The 
craigdo@3425
    84
   * method provided to do this is Join (). If you call Join() you will block
craigdo@3425
    85
   * until the SystemThread run method returns.
craigdo@3425
    86
   *
craigdo@3791
    87
   * @warning The SystemThread uses SIGALRM to wake threads that are possibly
craigdo@3791
    88
   * blocked on IO.
craigdo@3791
    89
   * @see Shutdown
craigdo@3791
    90
   *
craigdo@3425
    91
   * @warning I've made the system thread class look like a normal ns3 object
craigdo@3425
    92
   * with smart pointers, and living in the heap.  This makes it very easy to
craigdo@3425
    93
   * manage threads from a single master thread context.  You should be very
craigdo@3425
    94
   * aware though that I have not made Ptr multithread safe!  This means that
craigdo@3425
    95
   * if you pass Ptr<SystemThread> around in a multithreaded environment, it is
craigdo@3425
    96
   * possible that the reference count will get messed up since it is not an
craigdo@3425
    97
   * atomic operation.  CREATE AND MANAGE YOUR THREADS IN ONE PLACE -- LEAVE
craigdo@3425
    98
   * THE PTR THERE.
craigdo@3425
    99
   */
craigdo@3425
   100
  SystemThread(Callback<void> callback);
craigdo@3425
   101
craigdo@3425
   102
  /**
craigdo@3425
   103
   * @brief Destroy a SystemThread object.
craigdo@3425
   104
   *
craigdo@3425
   105
   */
craigdo@3425
   106
  ~SystemThread();
craigdo@3425
   107
craigdo@3425
   108
  /**
craigdo@3425
   109
   * Increment the reference count. This method should not be called
craigdo@3425
   110
   * by user code. Object instances are expected to be used in conjunction
craigdo@3425
   111
   * of the Ptr template which would make calling Ref unecessary and 
craigdo@3425
   112
   * dangerous.
craigdo@3425
   113
   */
craigdo@3425
   114
  inline void Ref (void) const;
craigdo@3425
   115
craigdo@3425
   116
  /**
craigdo@3425
   117
   * Decrement the reference count. This method should not be called
craigdo@3425
   118
   * by user code. Object instances are expected to be used in conjunction
craigdo@3425
   119
   * of the Ptr template which would make calling Ref unecessary and 
craigdo@3425
   120
   * dangerous.
craigdo@3425
   121
   */
craigdo@3425
   122
  inline void Unref (void) const;
craigdo@3425
   123
craigdo@3425
   124
  /**
craigdo@3425
   125
   * @brief Start a thread of execution, running the provided callback.
craigdo@3425
   126
   */
craigdo@3425
   127
  void Start (void);
craigdo@3425
   128
craigdo@3425
   129
  /**
craigdo@3425
   130
   * @brief Suspend the caller until the thread of execution, running the 
craigdo@3425
   131
   * provided callback, finishes.
craigdo@3425
   132
   */
craigdo@3425
   133
  void Join (void);
craigdo@3425
   134
craigdo@3791
   135
  /**
craigdo@3791
   136
   * @brief Indicates to a managed thread doing cooperative multithreading that
craigdo@3791
   137
   * its managing thread wants it to exit.
craigdo@3791
   138
   *
craigdo@3791
   139
   * It is often the case that we want a thread to be off doing work until such
craigdo@3791
   140
   * time as its job is done (typically when the simulation is done).  We then 
craigdo@3791
   141
   * want the thread to exit itself.  This method provides a consistent way for
craigdo@3791
   142
   * the managing thread to communicate with the managed thread.  After the
craigdo@3791
   143
   * manager thread calls this method, the Break() method will begin returning
craigdo@3791
   144
   * true, telling the managed thread to exit.
craigdo@3791
   145
   *
craigdo@3791
   146
   * This alone isn't really enough to merit these events, but in Unix, if a
craigdo@3791
   147
   * worker thread is doing blocking IO, it will need to be woken up from that
craigdo@3791
   148
   * read somehow.  This method also provides that functionality, by sending a
craigdo@3791
   149
   * SIGALRM signal to the possibly blocked thread.
craigdo@3791
   150
   *
craigdo@3792
   151
   * @warning Uses SIGALRM to notifiy threads possibly blocked on IO.  Beware
craigdo@3792
   152
   * if you are using signals.
craigdo@3791
   153
   * @see Break
craigdo@3791
   154
   */
craigdo@3791
   155
  void Shutdown (void);
craigdo@3791
   156
craigdo@3791
   157
  /**
craigdo@3791
   158
   * @brief Indicates to a thread doing cooperative multithreading that
craigdo@3791
   159
   * its managing thread wants it to exit.
craigdo@3791
   160
   *
craigdo@3791
   161
   * It is often the case that we want a thread to be off doing work until such
craigdo@3791
   162
   * time as its job is done.  We then want the thread to exit itself.  This
craigdo@3791
   163
   * method allows a thread to query whether or not it should be running.  
craigdo@3791
   164
   * Typically, the worker thread is running in a forever-loop, and will need to
craigdo@3791
   165
   * "break" out of that loop to exit -- thus the name.
craigdo@3791
   166
   *
craigdo@3791
   167
   * @see Shutdown
craigdo@3791
   168
   * @returns true if thread is expected to exit (break out of the forever-loop)
craigdo@3791
   169
   */
craigdo@3791
   170
  bool Break (void);
craigdo@3791
   171
craigdo@3425
   172
private:
craigdo@3425
   173
  SystemThreadImpl * m_impl;
craigdo@3425
   174
  mutable uint32_t m_count;
craigdo@3791
   175
  bool m_break;
craigdo@3425
   176
};
craigdo@3425
   177
craigdo@3425
   178
 void
craigdo@3425
   179
SystemThread::Ref (void) const
craigdo@3425
   180
{
craigdo@3425
   181
  m_count++;
craigdo@3425
   182
}
craigdo@3425
   183
craigdo@3425
   184
 void
craigdo@3425
   185
SystemThread::Unref (void) const
craigdo@3425
   186
{
craigdo@3425
   187
  m_count--;
craigdo@3425
   188
  if (m_count == 0)
craigdo@3425
   189
    {
craigdo@3425
   190
      delete this;
craigdo@3425
   191
    }
craigdo@3425
   192
}
craigdo@3425
   193
craigdo@3425
   194
} //namespace ns3
craigdo@3425
   195
craigdo@3425
   196
#endif /* SYSTEM_THREAD_H */
craigdo@3425
   197
craigdo@3425
   198