1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
13 #include <anna/core/functions.hpp>
15 #include <anna/core/mt/ThreadManager.hpp>
16 #include <anna/core/mt/Semaphore.hpp>
17 #include <anna/core/mt/Thread.hpp>
18 #include <anna/core/tracing/TraceMethod.hpp>
23 anna_assign_enum(ThreadManager::Mode) = { "None", "Unlimit", "ExceptionWhenFull", "LockWhenFull", NULL };
25 ThreadManager::ThreadManager(const char* name, const Mode::_v mode, const int maxSize, const int flags) :
30 a_threadFlags(flags) {
31 if(a_mode == Mode::LockWhenFull)
32 a_semaphore = new Semaphore(0);
35 ThreadManager::ThreadManager(const char* name, const int flags) :
37 a_mode(Mode::Unlimit),
40 a_threadFlags(flags) {
41 if(a_mode == Mode::LockWhenFull)
42 a_semaphore = new Semaphore(0);
45 ThreadManager::~ThreadManager() {
49 // Para que no intenten sacar el nombre del ThreadManager que los creĆ³
50 for(thread_iterator ii = thread_begin(), maxii = thread_end(); ii != maxii; ii ++) {
51 thread(ii)->a_manager = NULL;
55 a_semaphore->signal();
58 } catch(RuntimeException& ex) {
70 Thread* ThreadManager::createThread()
74 if(a_mode == Mode::None) {
75 string msg(asString());
76 msg += " | Invalid mode";
77 throw RuntimeException(msg, ANNA_FILE_LOCATION);
80 if(a_mode != Mode::Unlimit && a_maxSize <= 0) {
81 string msg(asString());
82 msg += " | Invalid max thread number";
83 throw RuntimeException(msg, ANNA_FILE_LOCATION);
86 Guard guard(this, "anna::ThreadManager::createThread");
87 const int size = Recycler <Thread>::size();
90 case Mode::ExceptionWhenFull:
92 if(a_maxSize == size) {
93 string msg(asString());
94 msg += " | No available threads";
95 throw RuntimeException(msg, ANNA_FILE_LOCATION);
98 // No hay "break" para que siga procesando
100 result = Recycler <Thread>::create();
102 case Mode::LockWhenFull:
104 if(a_maxSize == size) {
107 string msg(asString());
108 msg += " | Waiting for thread release";
109 Logger::debug(msg, ANNA_FILE_LOCATION);
113 string msg(asString());
114 msg += " | Achieve thread release";
115 Logger::debug(msg, ANNA_FILE_LOCATION);
117 Guard reopen(this, "anna::ThreadManager::createThread (after signal)");
118 result = Recycler <Thread>::create();
120 result = Recycler <Thread>::create();
126 result->a_manager = this;
127 result->setFlags(a_threadFlags);
129 string msg("ThreadManager::createThread | ");
132 msg += result->asString();
133 Logger::debug(msg, ANNA_FILE_LOCATION);
138 void ThreadManager::join()
141 string msg("ThreadManager::join (init) | ");
143 Logger::debug(msg, ANNA_FILE_LOCATION);
147 const pthread_t self(pthread_self());
148 pthread_t* threads = new pthread_t [Recycler <Thread>::size()];
151 for(thread_iterator ii = thread_begin(), maxii = thread_end(); ii != maxii; ii ++) {
152 threads [index] = thread(ii)->getId();
154 if(pthread_equal(threads [index], self) != 0) {
155 string msg(asString());
157 thread(ii)->asString();
158 msg += " | Threads owns to this Manager";
160 throw RuntimeException(msg, ANNA_FILE_LOCATION);
169 for(int ii = 0; ii < index; ii ++) {
170 if((errorCode = pthread_join(threads [ii], NULL)) != 0) {
171 string msg(asString());
172 msg += " | Bad join";
173 throw RuntimeException(msg, errorCode, ANNA_FILE_LOCATION);
180 string msg("ThreadManager::join (final) | ");
182 Logger::debug(msg, ANNA_FILE_LOCATION);
186 void ThreadManager::releaseThread(Thread* thread)
188 if(thread->isRunning() == true) {
189 string msg(thread->asString());
190 msg += " | Still activated";
191 throw RuntimeException(msg, ANNA_FILE_LOCATION);
194 if(a_mode == Mode::LockWhenFull) {
195 Guard guard(this, "anna::ThreadManager::releaseThread");
196 // No hace falta acceder mediate SafeRecycler porque ya tenemos una SSCC establecida.
197 const int size = Recycler <Thread>::getSize();
198 Recycler <Thread>::release(thread);
200 if(size == a_maxSize)
201 a_semaphore->signal();
203 SafeRecycler <Thread>::release(thread);
206 string msg("ThreadManager::releaseThread | ");
208 Logger::debug(msg, ANNA_FILE_LOCATION);
212 string ThreadManager::asString() const
214 string result("anna::ThreadManager { Name: ");
216 result += " | Mode: ";
217 result += Mode::asCString(a_mode);
218 result += " | MaxSize: ";
221 result += functions::asString(a_maxSize);
223 result += "<unlimited>";
225 result += functions::asText(" | Size: ", Recycler <Thread>::size());
226 return result += " }";