<commit_before>/*
 *
 *  D-Bus++ - C++ bindings for D-Bus
 *
 *  Copyright (C) 2005-2007  <NAME> <<EMAIL>>
 *
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <cassert>
#include <errno.h>

#include <dbus-c++/eventloop.h>
#include <dbus-c++/debug.h>

#include <sys/poll.h>
#include <sys/time.h>

#include <dbus/dbus.h>

using namespace DBus;

static double millis(timeval tv)
{
	return (tv.tv_sec *1000.0 + tv.tv_usec/1000.0);
}
	
DefaultTimeout::DefaultTimeout(int interval, bool repeat, DefaultMainLoop *ed)
: _enabled(true), _interval(interval), _repeat(repeat), _expiration(0), _data(0), _disp(ed)
{
	timeval now;
	gettimeofday(&now, NULL);

	_expiration = millis(now) + interval;

	_disp->_mutex_t.lock();
	_disp->_timeouts.push_back(this);
	_disp->_mutex_t.unlock();
}

DefaultTimeout::~DefaultTimeout()
{
	_disp->_mutex_t.lock();
	_disp->_timeouts.remove(this);
	_disp->_mutex_t.unlock();
}

DefaultWatch::DefaultWatch(int fd, int flags, DefaultMainLoop *ed)
: _enabled(true), _fd(fd), _flags(flags), _state(0), _data(0), _disp(ed)
{
	_disp->_mutex_w.lock();
	_disp->_watches.push_back(this);
	_disp->_mutex_w.unlock();
}

DefaultWatch::~DefaultWatch()
{
	_disp->_mutex_w.lock();
	_disp->_watches.remove(this);
	_disp->_mutex_w.unlock();
}

DefaultMutex::DefaultMutex()
{
	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
	pthread_mutex_init(&_mutex, &attr);
}

DefaultMutex::~DefaultMutex()
{
	pthread_mutex_destroy(&_mutex);
}

void DefaultMutex::lock()
{
	int r = pthread_mutex_lock(&_mutex);
	/* This assert is here to avoid a difficult-to-diagnose deadlock. See
	 * crosbug.com/8486 and crosbug.com/8596. */
	assert(r != EDEADLK);
}

void DefaultMutex::unlock()
{
	pthread_mutex_unlock(&_mutex);
}

DefaultMainLoop::DefaultMainLoop()
{
}

DefaultMainLoop::~DefaultMainLoop()
{
	_mutex_w.lock();

	DefaultWatches::iterator wi = _watches.begin();
	while (wi != _watches.end())
	{
		DefaultWatches::iterator wmp = wi;
		++wmp;
		_mutex_w.unlock();
		delete (*wi);
		_mutex_w.lock();
		wi = wmp;
	}
	_mutex_w.unlock();

	_mutex_t.lock();

	DefaultTimeouts::iterator ti = _timeouts.begin();
	while (ti != _timeouts.end())
	{
		DefaultTimeouts::iterator tmp = ti;
		++tmp;
		_mutex_t.unlock();
		delete (*ti);
		_mutex_t.lock();
		ti = tmp;
	}
	_mutex_t.unlock();
}

void DefaultMainLoop::dispatch()
{
	_mutex_w.lock();

	int nfd = _watches.size();

	if(_fdunlock)
	{
		nfd=nfd+2;
	}

	pollfd fds[nfd];

	DefaultWatches::iterator wi = _watches.begin();

	for (nfd = 0; wi != _watches.end(); ++wi)
	{
		if ((*wi)->enabled())
		{
			fds[nfd].fd = (*wi)->descriptor();
			fds[nfd].events = (*wi)->flags();
			fds[nfd].revents = 0;

			++nfd;
		}
	}

	if(_fdunlock){
		fds[nfd].fd = _fdunlock[0];
		fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
		fds[nfd].revents = 0;
		
		nfd++;
		fds[nfd].fd = _fdunlock[1];
		fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
		fds[nfd].revents = 0;
	}

	_mutex_w.unlock();

	int wait_min = 10000;

	DefaultTimeouts::iterator ti;

	_mutex_t.lock();

	for (ti = _timeouts.begin(); ti != _timeouts.end(); ++ti)
	{
		if ((*ti)->enabled() && (*ti)->interval() < wait_min)
			wait_min = (*ti)->interval();
	}

	_mutex_t.unlock();

	poll(fds, nfd, wait_min);

	timeval now;
	gettimeofday(&now, NULL);

	double now_millis = millis(now);

	_mutex_t.lock();

	ti = _timeouts.begin();

	while (ti != _timeouts.end())
	{
		DefaultTimeouts::iterator tmp = ti;<commit_msg>[dbus-c++] fix spurious wakeups<commit_after>/*
 *
 *  D-Bus++ - C++ bindings for D-Bus
 *
 *  Copyright (C) 2005-2007  <NAME> <<EMAIL>>
 *
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <cassert>
#include <errno.h>

#include <dbus-c++/eventloop.h>
#include <dbus-c++/debug.h>

#include <sys/poll.h>
#include <sys/time.h>

#include <dbus/dbus.h>

using namespace DBus;

static double millis(timeval tv)
{
	return (tv.tv_sec *1000.0 + tv.tv_usec/1000.0);
}
	
DefaultTimeout::DefaultTimeout(int interval, bool repeat, DefaultMainLoop *ed)
: _enabled(true), _interval(interval), _repeat(repeat), _expiration(0), _data(0), _disp(ed)
{
	timeval now;
	gettimeofday(&now, NULL);

	_expiration = millis(now) + interval;

	_disp->_mutex_t.lock();
	_disp->_timeouts.push_back(this);
	_disp->_mutex_t.unlock();
}

DefaultTimeout::~DefaultTimeout()
{
	_disp->_mutex_t.lock();
	_disp->_timeouts.remove(this);
	_disp->_mutex_t.unlock();
}

DefaultWatch::DefaultWatch(int fd, int flags, DefaultMainLoop *ed)
: _enabled(true), _fd(fd), _flags(flags), _state(0), _data(0), _disp(ed)
{
	_disp->_mutex_w.lock();
	_disp->_watches.push_back(this);
	_disp->_mutex_w.unlock();
}

DefaultWatch::~DefaultWatch()
{
	_disp->_mutex_w.lock();
	_disp->_watches.remove(this);
	_disp->_mutex_w.unlock();
}

DefaultMutex::DefaultMutex()
{
	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
	pthread_mutex_init(&_mutex, &attr);
}

DefaultMutex::~DefaultMutex()
{
	pthread_mutex_destroy(&_mutex);
}

void DefaultMutex::lock()
{
	int r = pthread_mutex_lock(&_mutex);
	/* This assert is here to avoid a difficult-to-diagnose deadlock. See
	 * crosbug.com/8486 and crosbug.com/8596. */
	assert(r != EDEADLK);
}

void DefaultMutex::unlock()
{
	pthread_mutex_unlock(&_mutex);
}

DefaultMainLoop::DefaultMainLoop()
{
}

DefaultMainLoop::~DefaultMainLoop()
{
	_mutex_w.lock();

	DefaultWatches::iterator wi = _watches.begin();
	while (wi != _watches.end())
	{
		DefaultWatches::iterator wmp = wi;
		++wmp;
		_mutex_w.unlock();
		delete (*wi);
		_mutex_w.lock();
		wi = wmp;
	}
	_mutex_w.unlock();

	_mutex_t.lock();

	DefaultTimeouts::iterator ti = _timeouts.begin();
	while (ti != _timeouts.end())
	{
		DefaultTimeouts::iterator tmp = ti;
		++tmp;
		_mutex_t.unlock();
		delete (*ti);
		_mutex_t.lock();
		ti = tmp;
	}
	_mutex_t.unlock();
}

void DefaultMainLoop::dispatch()
{
	_mutex_w.lock();

	int nfd = _watches.size();

	if(_fdunlock)
	{
		nfd=nfd+2;
	}

	pollfd fds[nfd];

	DefaultWatches::iterator wi = _watches.begin();

	for (nfd = 0; wi != _watches.end(); ++wi)
	{
		if ((*wi)->enabled())
		{
			fds[nfd].fd = (*wi)->descriptor();
			fds[nfd].events = (*wi)->flags();
			fds[nfd].revents = 0;

			++nfd;
		}
	}

	if(_fdunlock){
		fds[nfd].fd = _fdunlock[0];
		fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
		fds[nfd].revents = 0;
		
		nfd++;
		fds[nfd].fd = _fdunlock[1];
		fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
		fds[nfd].revents = 0;
	}

	_mutex_w.unlock();

	int wait_min = -1;

	DefaultTimeouts::iterator ti;

	_mutex_t.lock();

	for (ti = _timeouts.begin(); ti != _timeouts.end(); ++ti)
	{
		if (((*ti)->enabled() && (*ti)->interval() < wait_min) || (wait_min < 0))
			wait_min = (*ti)->interval();
	}

	_mutex_t.unlock();

	poll(fds, nfd, wait_min);

	timeval now;
	gettimeofday(&now, NULL);

	double now_millis = millis(now);

	_mutex_t.lock();

	ti = _timeouts.begin();

	while (ti != _timeouts.end())
	{
		DefaultTimeouts::iterator tmp = ti;
{'fraction_non_alphanumeric': 0.16154841746087775, 'fraction_numerical': 0.013295681844922932, 'mean_word_length': 4.386565272496831, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5171161', 'n_tokens_mistral': 3452, 'n_tokens_neox': 3236, 'n_words': 720}