Changeset 7:07dd445b7fac in rrlib_thread


Ignore:
Timestamp:
25.11.2012 21:34:03 (7 years ago)
Author:
Max Reichardt <mreichardt@…>
Branch:
default
Phase:
public
Message:

Added method to actually set niceness level of thread.
Thread id is now a unique 32 bit integer.
As discussed with Tobias, threads no longer catch all exceptions - so that they no longer 'get lost' and a stack trace is available.
If they are not handled somewhere else, the process terminates.

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • tLoopThread.cpp

    r6 r7  
    149149void tLoopThread::Run() 
    150150{ 
    151   try 
    152   { 
    153     //stopSignal = false; // this may lead to unintended behaviour 
    154  
    155     // Start main loop 
    156     MainLoop(); 
    157   } 
    158   catch (const std::exception& e) 
    159   { 
    160     RRLIB_LOG_PRINT(ERROR, "Uncaught Exception: ", e); 
    161   } 
     151  // Start main loop 
     152  MainLoop(); 
    162153} 
    163154 
  • tThread.cpp

    r5 r7  
    3535#include <sstream> 
    3636#include <cstring> 
     37#include <sys/resource.h> 
     38#include <sys/syscall.h> 
    3739#include "rrlib/design_patterns/singleton.h" 
    38  
    3940//---------------------------------------------------------------------- 
    4041// Internal includes with "" 
     
    125126}; 
    126127 
    127 /*! Thread counter - used for generating names */ 
    128 static std::atomic<int>& GetThreadCounter() 
    129 { 
    130   static std::atomic<int> thread_counter; 
    131   return thread_counter; 
    132 } 
    133  
    134128/*! List of threads currently known and running (== all thread objects created) */ 
    135129static std::shared_ptr<internal::tVectorWithMutex<std::weak_ptr<tThread>>>& GetThreadList() 
     
    138132  return thread_list; 
    139133} 
     134 
     135static uint32_t GetUniqueThreadId() 
     136{ 
     137  static tOrderedMutex mutex("GetUniqueThreadId()", 0x7FFFFFFE); 
     138  static bool overflow = false; 
     139  static uint32_t counter = 1; 
     140  tLock lock(mutex); 
     141  if (!overflow) 
     142  { 
     143    int result = counter; 
     144    counter++; 
     145    if (counter == 0) 
     146    { 
     147      overflow = true; 
     148    } 
     149    return result; 
     150  } 
     151 
     152  tLock lock2(GetThreadList()->obj_mutex); 
     153  // hmm... we start at id 1024 - as the former threads may be more long-lived 
     154  counter = std::max(1023u, counter); 
     155  std::vector<std::weak_ptr<tThread>>& current_threads = GetThreadList()->vec; 
     156  while (true) 
     157  { 
     158    counter++; 
     159    bool used = false; 
     160    for (auto it = current_threads.begin(); it != current_threads.end(); ++it) 
     161    { 
     162      std::shared_ptr<tThread> thread = it->lock(); 
     163      if (thread && thread->GetId() == counter) 
     164      { 
     165        used = true; 
     166        break; 
     167      } 
     168    } 
     169    if (!used) 
     170    { 
     171      return counter; 
     172    } 
     173  } 
     174} 
     175 
    140176 
    141177} // namespace internal 
     
    144180  stop_signal(false), 
    145181  lock_stack(), 
    146   id(internal::GetThreadCounter()++), 
     182  id(internal::GetUniqueThreadId()), 
    147183  name(internal::GetDefaultThreadName(id)), 
    148184  priority(cDEFAULT_PRIORITY), 
     
    177213  stop_signal(false), 
    178214  lock_stack(), 
    179   id(internal::GetThreadCounter()++), 
     215  id(internal::GetUniqueThreadId()), 
    180216  name(name.length() > 0 ? name : internal::GetDefaultThreadName(id)), 
    181217  priority(cDEFAULT_PRIORITY), 
     
    325361  if (start_signal && (!(stop_signal))) 
    326362  { 
    327     try 
    328     { 
    329       l.Unlock(); 
    330       RRLIB_LOG_PRINT(DEBUG, "Thread started"); 
    331       Run(); 
    332       RRLIB_LOG_PRINT(DEBUG, "Thread exited normally"); 
    333     } 
    334     catch (const std::exception& e) 
    335     { 
    336       RRLIB_LOG_PRINT(ERROR, "Thread exited because of exception: ", e.what()); 
    337     } 
     363    l.Unlock(); 
     364    RRLIB_LOG_PRINT(DEBUG, "Thread started"); 
     365    Run(); 
     366    RRLIB_LOG_PRINT(DEBUG, "Thread exited normally"); 
    338367  } 
    339368 
     
    382411} 
    383412 
     413void tThread::SetPriority(int new_priority) 
     414{ 
     415  //if (new_priority < sched_get_priority_min(SCHED_OTHER) || new_priority > sched_get_priority_max(SCHED_OTHER)) 
     416  if (new_priority < -20 || new_priority > 19) 
     417  { 
     418    //pthread_getschedparam(handle, &policy, &param); 
     419    RRLIB_LOG_PRINT(ERROR, "Invalid thread priority: ", new_priority, ". Ignoring.");// Valid range is ", sched_get_priority_min(SCHED_OTHER), " to ", sched_get_priority_max(SCHED_OTHER), 
     420    //    ". Current priority is ", param.sched_priority, "."); 
     421    return; 
     422  } 
     423  if (CurrentThreadId() != GetId()) 
     424  { 
     425    RRLIB_LOG_PRINT(ERROR, "SetPriority can only be called from the current thread"); 
     426    return; 
     427  } 
     428 
     429  //int error_code = pthread_setschedparam(handle, SCHED_OTHER, &param); 
     430  // works according to "man pthreads" and discussion on: http://stackoverflow.com/questions/7684404/is-nice-used-to-change-the-thread-priority-or-the-process-priority 
     431  pid_t thread_id = syscall(SYS_gettid); 
     432  int error_code = setpriority(PRIO_PROCESS, thread_id, new_priority); 
     433  if (error_code) 
     434  { 
     435    RRLIB_LOG_PRINT(ERROR, "Failed to change thread priority: ", strerror(error_code)); 
     436    return; 
     437  } 
     438  RRLIB_LOG_PRINT(DEBUG_VERBOSE_1, "Set niceness to ", new_priority); 
     439  priority = new_priority; 
     440} 
     441 
    384442void tThread::SetRealtime() 
    385443{ 
    386444  struct sched_param param; 
    387445  param.sched_priority = 49; 
    388   if (pthread_setschedparam(handle, SCHED_FIFO, &param)) 
     446  int error_code = pthread_setschedparam(handle, SCHED_FIFO, &param); 
     447  if (error_code) 
    389448  { 
    390449    //printf("Failed making thread a real-time thread. Possibly current user has insufficient rights.\n"); 
    391     RRLIB_LOG_PRINT(ERROR, "Failed making thread a real-time thread. Possibly current user has insufficient rights."); 
     450    RRLIB_LOG_PRINT(ERROR, "Failed making thread a real-time thread.", (error_code == EPERM ? " Caller does not have appropriate privileges." : "")); 
    392451  } 
    393452} 
  • tThread.h

    r5 r7  
    9696 
    9797  typedef std::thread tWrappedThread; 
     98  typedef uint32_t tThreadId; 
    9899 
    99100  /*! 
     
    111112   * \return Current thread id 
    112113   */ 
    113   inline static int64_t CurrentThreadId() 
     114  inline static tThreadId CurrentThreadId() 
    114115  { 
    115116    return CurrentThread().GetId(); 
     
    146147  /*! 
    147148   * \return Returns the rrlib ID of this Thread. 
    148    */ 
    149   inline int GetId() const 
     149   * 
     150   * The thread id is unique for quite a long time (until 2^32 threads 
     151   * have been spawned. After that, it is guaranteed that all existing threads 
     152   * have different ids. Ids repeat less than every 2^31 threads) 
     153   * A thread id is never zero 
     154   */ 
     155  inline tThreadId GetId() const 
    150156  { 
    151157    return id; 
     
    272278  /*! 
    273279   * \param new_priority New priority for thread 
    274    */ 
    275   void SetPriority(int new_priority) 
    276   { 
    277     // TODO: currently does nothing 
    278     priority = new_priority; 
    279   } 
     280   * (values as for Linux' niceness: -20 Highest priority, 0 default, 19 Lowest) 
     281   * Can only be called for the current thread! 
     282   */ 
     283  void SetPriority(int new_priority); 
    280284 
    281285  /*! 
     
    379383 
    380384  /*! Id of Thread - generated by this class */ 
    381   const int id; 
     385  const tThreadId id; 
    382386 
    383387  /*! Name of Thread */ 
Note: See TracChangeset for help on using the changeset viewer.