winix/winixd/core/threadmanager.cpp

171 lines
3.8 KiB
C++

/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2011-2014, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <signal.h>
#include "threadmanager.h"
#include "log.h"
namespace Winix
{
ThreadManager::ThreadManager()
{
were_started = false;
}
void ThreadManager::SetSynchro(Synchro * psynchro)
{
synchro = psynchro;
}
void ThreadManager::Init()
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGTERM);
sigaddset(&set, SIGINT);
// blocking SIGTERM and SIGINT
// new threads will have the signals blocked too
pthread_sigmask(SIG_BLOCK, &set, 0);
}
void ThreadManager::Add(BaseThread * pbase, const wchar_t * thread_name)
{
ThreadItem item;
item.object = pbase;
item.name = thread_name;
thread_tab.push_back(item);
if( were_started )
Start(thread_tab.size() - 1);
else
log << log4 << "TM: added a thread to the queue, number: " << (thread_tab.size()-1)
<< ", name: " << thread_name << logend;
}
void ThreadManager::Add(BaseThread & pbase, const wchar_t * thread_name)
{
Add(&pbase, thread_name);
}
void ThreadManager::Add(BaseThread * pbase, const std::wstring & thread_name)
{
Add(pbase, thread_name.c_str());
}
void ThreadManager::Add(BaseThread & pbase, const std::wstring & thread_name)
{
Add(&pbase, thread_name.c_str());
}
void ThreadManager::StartAll()
{
synchro->Lock();
for(size_t i=0 ; i<thread_tab.size() ; ++i)
Start(i);
synchro->Unlock();
were_started = true;
}
void ThreadManager::Start(size_t i)
{
if( i < thread_tab.size() )
{
thread_tab[i].object->SetSynchro(synchro);
if( thread_tab[i].object->StartThread() )
{
log << log4 << "TM: thread " << i << " (" << thread_tab[i].object->ThreadId() << ", name: "
<< thread_tab[i].name << ") started" << logend;
}
else
{
log << log4 << "TM: cannot run a thread, thread number: " << i
<< ", name: " << thread_tab[i].name << logend;
}
}
}
void ThreadManager::StopAll()
{
if( !were_started )
return;
// WakeUpThread() should be used with Lock/Unlock
synchro->Lock();
for(size_t i=0 ; i<thread_tab.size() ; ++i)
thread_tab[i].object->WakeUpThread();
synchro->Unlock();
for(size_t i=0 ; i<thread_tab.size() ; ++i)
{
log << log4 << "TM: waiting for thread " << i << " (" << thread_tab[i].object->ThreadId()
<< ", name: " << thread_tab[i].name << ")" << logend;
thread_tab[i].object->WaitForThread();
log << log4 << "TM: thread " << i << " terminated" << logend;
}
}
} // namespace Winix