{
Dictionary::Ptr dictionary = boost::make_shared<Dictionary>();
- if (json->type != cJSON_Object)
- BOOST_THROW_EXCEPTION(std::invalid_argument("JSON type must be cJSON_Object."));
+ ASSERT(json->type == cJSON_Object);
for (cJSON *i = json->child; i != NULL; i = i->next) {
dictionary->Set(i->string, Value::FromJson(i));
#include <boost/bind.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/foreach.hpp>
+#include <boost/chrono/duration.hpp>
using namespace icinga;
ThreadPool::ThreadPool(void)
- : m_Stopped(false), m_ThreadDeaths(0), m_WaitTime(0), m_ServiceTime(0), m_TaskCount(0)
+ : m_Stopped(false), m_ThreadDeaths(0), m_WaitTime(0),
+ m_ServiceTime(0), m_TaskCount(0)
{
for (int i = 0; i < 2; i++)
SpawnWorker();
- boost::thread managerThread(boost::bind(&ThreadPool::ManagerThreadProc, this));
- managerThread.detach();
-
- boost::thread statsThread(boost::bind(&ThreadPool::StatsThreadProc, this));
- statsThread.detach();
+ m_ManagerThread = boost::thread(boost::bind(&ThreadPool::ManagerThreadProc, this));
+ m_StatsThread = boost::thread(boost::bind(&ThreadPool::StatsThreadProc, this));
}
ThreadPool::~ThreadPool(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
m_Stopped = true;
- m_CV.notify_all();
+ m_WorkCV.notify_all();
+ m_MgmtCV.notify_all();
}
/**
Utility::Sleep(0.5);
lock.lock();
}
+
+ int alive;
+
+ do {
+ alive = 0;
+ for (int i = 0; i < sizeof(m_ThreadStats) / sizeof(m_ThreadStats[0]); i++) {
+ if (m_ThreadStats[i].State != ThreadDead) {
+ alive++;
+ KillWorker();
+ }
+ }
+
+ if (alive > 0) {
+ lock.unlock();
+ Utility::Sleep(0.5);
+ lock.lock();
+ }
+ } while (alive > 0);
+
+ m_ManagerThread.join();
+ m_StatsThread.join();
}
/**
UpdateThreadUtilization(tid, ThreadIdle);
while (m_WorkItems.empty() && !m_Stopped && m_ThreadDeaths == 0)
- m_CV.wait(lock);
+ m_WorkCV.wait(lock);
if (m_ThreadDeaths > 0) {
m_ThreadDeaths--;
wi.Timestamp = Utility::GetTime();
m_WorkItems.push_back(wi);
- m_CV.notify_one();
+ m_WorkCV.notify_one();
}
void ThreadPool::ManagerThreadProc(void)
Utility::SetThreadName(idbuf.str());
for (;;) {
- Utility::Sleep(5);
-
- double now = Utility::GetTime();
-
int pending, alive;
double avg_latency, max_latency;
double utilization = 0;
{
boost::mutex::scoped_lock lock(m_Mutex);
+
+ m_MgmtCV.timed_wait(lock, boost::posix_time::seconds(5));
+
+ if (m_Stopped)
+ break;
+
pending = m_WorkItems.size();
alive = 0;
Utility::SetThreadName(idbuf.str());
for (;;) {
- Utility::Sleep(0.25);
+ boost::mutex::scoped_lock lock(m_Mutex);
- {
- boost::mutex::scoped_lock lock(m_Mutex);
+ m_MgmtCV.timed_wait(lock, boost::posix_time::milliseconds(250));
- for (int i = 0; i < sizeof(m_ThreadStats) / sizeof(m_ThreadStats[0]); i++)
- UpdateThreadUtilization(i);
- }
+ if (m_Stopped)
+ break;
+
+ for (int i = 0; i < sizeof(m_ThreadStats) / sizeof(m_ThreadStats[0]); i++)
+ UpdateThreadUtilization(i);
}
}
ThreadStats m_ThreadStats[512];
int m_ThreadDeaths;
+ boost::thread m_ManagerThread;
+ boost::thread m_StatsThread;
+
double m_WaitTime;
double m_ServiceTime;
int m_TaskCount;
double m_MaxLatency;
boost::mutex m_Mutex;
- boost::condition_variable m_CV;
+ boost::condition_variable m_WorkCV;
+ boost::condition_variable m_MgmtCV;
bool m_Stopped;
#include "base/timer.h"
#include "base/application.h"
#include "base/utility.h"
+#include "base/logger_fwd.h"
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
lock.unlock();
/* Asynchronously call the timer. */
- Application::GetTP().Post(boost::bind(&Timer::Call, timer));
+ Utility::QueueAsyncCallback(boost::bind(&Timer::Call, timer));
}
}
base-dictionary.cpp \
base-fifo.cpp \
base-object.cpp \
- base-shellescape.cpp
+ base-shellescape.cpp \
+ base-timer.cpp
icinga2_test_CPPFLAGS = \
$(BOOST_CPPFLAGS) \
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "base/timer.h"
+#include "base/utility.h"
+#include "base/application.h"
+#include <boost/test/unit_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/foreach.hpp>
+#include <iostream>
+
+using namespace icinga;
+
+struct TimerFixture
+{
+ TimerFixture(void)
+ {
+ Timer::Initialize();
+ }
+
+ ~TimerFixture(void)
+ {
+ Timer::Uninitialize();
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(base_timer, TimerFixture)
+
+BOOST_AUTO_TEST_CASE(construct)
+{
+ Timer::Ptr timer = boost::make_shared<Timer>();
+ BOOST_CHECK(timer);
+}
+
+BOOST_AUTO_TEST_CASE(interval)
+{
+ Timer::Ptr timer = boost::make_shared<Timer>();
+ timer->SetInterval(1.5);
+ BOOST_CHECK(timer->GetInterval() == 1.5);
+}
+
+static void Callback(int *counter)
+{
+ (*counter)++;
+}
+
+BOOST_AUTO_TEST_CASE(invoke)
+{
+ int counter;
+ Timer::Ptr timer = boost::make_shared<Timer>();
+ timer->OnTimerExpired.connect(boost::bind(&Callback, &counter));
+ timer->SetInterval(1);
+
+ counter = 0;
+ timer->Start();
+ Utility::Sleep(5.5);
+ timer->Stop();
+
+ std::cout << counter << std::endl;
+ BOOST_CHECK(counter >= 4 && counter <= 6);
+}
+
+BOOST_AUTO_TEST_CASE(scope)
+{
+ int counter;
+ Timer::Ptr timer = boost::make_shared<Timer>();
+ timer->OnTimerExpired.connect(boost::bind(&Callback, &counter));
+ timer->SetInterval(1);
+
+ counter = 0;
+ timer->Start();
+ Utility::Sleep(5.5);
+ timer.reset();
+ Utility::Sleep(5.5);
+
+ std::cout << counter << std::endl;
+ BOOST_CHECK(counter >= 4 && counter <= 6);
+}
+
+BOOST_AUTO_TEST_SUITE_END()