OregonCore  revision be9e804-git
Your Favourite TBC server
Threading.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "Threading.h"
19 #include "Errors.h"
20 #include <ace/OS_NS_unistd.h>
21 #include <ace/Sched_Params.h>
22 #include <vector>
23 
24 #if PLATFORM == PLATFORM_UNIX
25 #include "Debugging/UnixDebugger.h"
26 #endif
27 
28 using namespace ACE_Based;
29 
31 {
32  for (int i = Idle; i < MAXPRIORITYNUM; ++i)
33  m_priority[i] = ACE_THR_PRI_OTHER_DEF;
34 
35  m_priority[Idle] = ACE_Sched_Params::priority_min(ACE_SCHED_OTHER);
36  m_priority[Realtime] = ACE_Sched_Params::priority_max(ACE_SCHED_OTHER);
37 
38  std::vector<int> _tmp;
39 
40  ACE_Sched_Params::Policy _policy = ACE_SCHED_OTHER;
41  ACE_Sched_Priority_Iterator pr_iter(_policy);
42 
43  while (pr_iter.more())
44  {
45  _tmp.push_back(pr_iter.priority());
46  pr_iter.next();
47  }
48 
49  ASSERT (!_tmp.empty());
50 
51  if (_tmp.size() >= MAXPRIORITYNUM)
52  {
53  const size_t max_pos = _tmp.size();
54  size_t min_pos = 1;
55  size_t norm_pos = 0;
56  for (size_t i = 0; i < max_pos; ++i)
57  {
58  if (_tmp[i] == ACE_THR_PRI_OTHER_DEF)
59  {
60  norm_pos = i + 1;
61  break;
62  }
63  }
64 
65  //since we have only 7(seven) values in enum Priority
66  //and 3 we know already (Idle, Normal, Realtime) so
67  //we need to split each list [Idle...Normal] and [Normal...Realtime]
68  //into � piesces
69  const size_t _divider = 4;
70  size_t _div = (norm_pos - min_pos) / _divider;
71  if (_div == 0)
72  _div = 1;
73 
74  min_pos = (norm_pos - 1);
75 
76  m_priority[Low] = _tmp[min_pos -= _div];
77  m_priority[Lowest] = _tmp[min_pos -= _div ];
78 
79  _div = (max_pos - norm_pos) / _divider;
80  if (_div == 0)
81  _div = 1;
82 
83  min_pos = norm_pos - 1;
84 
85  m_priority[High] = _tmp[min_pos += _div];
86  m_priority[Highest] = _tmp[min_pos += _div];
87  }
88 }
89 
91 {
92  if (p < Idle)
93  p = Idle;
94 
95  if (p > Realtime)
96  p = Realtime;
97 
98  return m_priority[p];
99 }
100 
101 #define THREADFLAG (THR_NEW_LWP | THR_SCHED_DEFAULT| THR_JOINABLE)
102 
103 Thread::Thread() : m_iThreadId(0), m_hThreadHandle(0), m_task(0)
104 {
105 }
106 
108 {
109  // register reference to m_task to prevent it deeltion until destructor
110  if (m_task)
111  m_task->incReference();
112 
113  bool _start = start();
114  ASSERT (_start);
115 }
116 
118 {
119  //Wait();
120 
121  // deleted runnable object (if no other references)
122  if (m_task)
123  m_task->decReference();
124 }
125 
126 //initialize Thread's class static member
129 
131 {
132  if (m_task == 0 || m_iThreadId != 0)
133  return false;
134 
135  bool res = (ACE_Thread::spawn(&Thread::ThreadTask, (void*)m_task, THREADFLAG, &m_iThreadId, &m_hThreadHandle) == 0);
136 
137  if (res)
138  m_task->incReference();
139 
140  return res;
141 }
142 
144 {
145  if (!m_hThreadHandle || !m_task)
146  return false;
147 
148  ACE_THR_FUNC_RETURN _value = ACE_THR_FUNC_RETURN(-1);
149  int _res = ACE_Thread::join(m_hThreadHandle, &_value);
150 
151  m_iThreadId = 0;
152  m_hThreadHandle = 0;
153 
154  return (_res == 0);
155 }
156 
157 bool Thread::kill(int signal)
158 {
159  if (!m_iThreadId || !m_task)
160  return false;
161 
162  return ACE_Thread::kill(m_iThreadId, signal) != 0;
163 }
164 
166 {
167  ACE_Thread::suspend(m_hThreadHandle);
168 }
169 
171 {
172  ACE_Thread::resume(m_hThreadHandle);
173 }
174 
175 ACE_THR_FUNC_RETURN Thread::ThreadTask(void* param)
176 {
177  #if PLATFORM == PLATFORM_UNIX
178  // unblock signal delivery for this thread
179  sigset_t ss;
180  sigfillset(&ss);
181  ACE_Thread::sigsetmask(SIG_UNBLOCK, &ss, NULL);
182 
184  #endif
185 
186  Runnable* _task = (Runnable*)param;
187  _task->run();
188 
189  #if PLATFORM == PLATFORM_UNIX
191  #endif
192 
193  // task execution complete, free referecne added at
194  _task->decReference();
195 
196  return (ACE_THR_FUNC_RETURN)0;
197 }
198 
199 ACE_thread_t Thread::currentId()
200 {
201  return ACE_Thread::self();
202 }
203 
204 ACE_hthread_t Thread::currentHandle()
205 {
206  ACE_hthread_t _handle;
207  ACE_Thread::self(_handle);
208 
209  return _handle;
210 }
211 
213 {
214  Thread* _thread = m_ThreadStorage.ts_object();
215  if (!_thread)
216  {
217  _thread = new Thread();
218  _thread->m_iThreadId = Thread::currentId();
220 
221  Thread* _oldValue = m_ThreadStorage.ts_object(_thread);
222  if (_oldValue)
223  delete _oldValue;
224  }
225 
226  return _thread;
227 }
228 
230 {
231  int _priority = m_TpEnum.getPriority(type);
232  int _ok = ACE_Thread::setprio(m_hThreadHandle, _priority);
233  //remove this ASSERT in case you don't want to know is thread priority change was successful or not
234  ASSERT (_ok == 0);
235 }
236 
237 void Thread::Sleep(unsigned long msecs)
238 {
239  ACE_OS::sleep(ACE_Time_Value(0, 1000 * msecs));
240 }
static ACE_THR_FUNC_RETURN ThreadTask(void *param)
Definition: Threading.cpp:175
static ACE_hthread_t currentHandle()
Definition: Threading.cpp:204
virtual void run()=0
static Thread * current()
Definition: Threading.cpp:212
static ThreadStorage m_ThreadStorage
Definition: Threading.h:107
static ACE_thread_t currentId()
Definition: Threading.cpp:199
ACE_hthread_t m_hThreadHandle
Definition: Threading.h:102
bool kill(int signal)
Definition: Threading.cpp:157
ACE_thread_t m_iThreadId
Definition: Threading.h:101
int getPriority(Priority p) const
Definition: Threading.cpp:90
static void Sleep(unsigned long msecs)
Definition: Threading.cpp:237
#define MAXPRIORITYNUM
Definition: Threading.h:60
static void InsertThread(ACE_thread_t thread)
Call this when new thread spawns.
#define THREADFLAG
Definition: Threading.cpp:101
static void RemoveThread(ACE_thread_t thread)
Call this when thread exits.
void setPriority(Priority type)
Definition: Threading.cpp:229
int m_priority[MAXPRIORITYNUM]
Definition: Threading.h:69
Runnable * m_task
Definition: Threading.h:103
static ThreadPriority m_TpEnum
Definition: Threading.h:109
#define ASSERT
Definition: Errors.h:29
ACE_TSS< Thread > ThreadStorage
Definition: Threading.h:105