Skip to content

Commit

Permalink
Update dir_monitor and adjust to API change
Browse files Browse the repository at this point in the history
  • Loading branch information
Semoar committed May 15, 2016
1 parent db96420 commit e6874fd
Show file tree
Hide file tree
Showing 11 changed files with 1,788 additions and 886 deletions.
186 changes: 103 additions & 83 deletions extras/dirwatch/basic_dir_monitor.hpp
Original file line number Diff line number Diff line change
@@ -1,83 +1,103 @@
//
// Copyright (c) 2008, 2009 Boris Schaeling <boris@highscore.de>
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_ASIO_BASIC_DIR_MONITOR_HPP
#define BOOST_ASIO_BASIC_DIR_MONITOR_HPP

#include <boost/asio.hpp>
#include <string>

namespace boost {
namespace asio {

struct dir_monitor_event
{
enum event_type
{
null = 0,
added = 1,
removed = 2,
modified = 3,
renamed_old_name = 4,
renamed_new_name = 5
};

dir_monitor_event()
: type(null) { }

dir_monitor_event(const std::string &d, const std::string &f, event_type t)
: dirname(d), filename(f), type(t) { }

std::string dirname;
std::string filename;
event_type type;
};

template <typename Service>
class basic_dir_monitor
: public boost::asio::basic_io_object<Service>
{
public:
explicit basic_dir_monitor(boost::asio::io_service &io_service)
: boost::asio::basic_io_object<Service>(io_service)
{
}

void add_directory(const std::string &dirname)
{
this->service.add_directory(this->implementation, dirname);
}

void remove_directory(const std::string &dirname)
{
this->service.remove_directory(this->implementation, dirname);
}

dir_monitor_event monitor()
{
boost::system::error_code ec;
dir_monitor_event ev = this->service.monitor(this->implementation, ec);
boost::asio::detail::throw_error(ec);
return ev;
}

dir_monitor_event monitor(boost::system::error_code &ec)
{
return this->service.monitor(this->implementation, ec);
}

template <typename Handler>
void async_monitor(Handler handler)
{
this->service.async_monitor(this->implementation, handler);
}
};

}
}

#endif
//
// Copyright (c) 2008, 2009 Boris Schaeling <boris@highscore.de>
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once

#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#include <string>

namespace boost {
namespace asio {

struct dir_monitor_event
{
enum event_type
{
null = 0,
added = 1,
removed = 2,
modified = 3,
renamed_old_name = 4,
renamed_new_name = 5,
/**
* In some cases a recursive scan of directory under dirname is required.
*/
recursive_rescan = 6
};

dir_monitor_event()
: type(null) { }

dir_monitor_event(const boost::filesystem::path &p, event_type t)
: path(p), type(t) { }

const char* type_cstr() const
{
switch(type) {
case boost::asio::dir_monitor_event::added: return "ADDED";
case boost::asio::dir_monitor_event::removed: return "REMOVED";
case boost::asio::dir_monitor_event::modified: return "MODIFIED";
case boost::asio::dir_monitor_event::renamed_old_name: return "RENAMED (OLD NAME)";
case boost::asio::dir_monitor_event::renamed_new_name: return "RENAMED (NEW NAME)";
case boost::asio::dir_monitor_event::recursive_rescan: return "RESCAN DIR";
default: return "UNKNOWN";
}
}

boost::filesystem::path path;
event_type type;
};

inline std::ostream& operator << (std::ostream& os, dir_monitor_event const& ev)
{
os << "dir_monitor_event " << ev.type_cstr() << " " << ev.path;
return os;
}

template <typename Service>
class basic_dir_monitor
: public boost::asio::basic_io_object<Service>
{
public:
explicit basic_dir_monitor(boost::asio::io_service &io_service)
: boost::asio::basic_io_object<Service>(io_service)
{
}

void add_directory(const std::string &dirname)
{
this->get_service().add_directory(this->get_implementation(), dirname);
}

void remove_directory(const std::string &dirname)
{
this->get_service().remove_directory(this->get_implementation(), dirname);
}

dir_monitor_event monitor()
{
boost::system::error_code ec;
dir_monitor_event ev = this->get_service().monitor(this->get_implementation(), ec);
boost::asio::detail::throw_error(ec);
return ev;
}

dir_monitor_event monitor(boost::system::error_code &ec)
{
return this->get_service().monitor(this->get_implementation(), ec);
}

template <typename Handler>
void async_monitor(Handler handler)
{
this->get_service().async_monitor(this->get_implementation(), handler);
}
};

}
}

47 changes: 25 additions & 22 deletions extras/dirwatch/dir_monitor.hpp
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
//
// Copyright (c) 2008, 2009 Boris Schaeling <boris@highscore.de>
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
//
// Copyright (c) 2008, 2009 Boris Schaeling <boris@highscore.de>
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once

#ifndef BOOST_ASIO_DIR_MONITOR_HPP
#define BOOST_ASIO_DIR_MONITOR_HPP
#include "basic_dir_monitor.hpp"
#include <boost/predef/os.h>

#include "basic_dir_monitor.hpp"
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
# include "windows/basic_dir_monitor_service.hpp"
#elif defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || defined(__FreeBSD__)
# include "inotify/basic_dir_monitor_service.hpp"
#else
# error "Platform not supported."
#endif
#if BOOST_OS_WINDOWS
# include "windows/basic_dir_monitor_service.hpp"
#elif (BOOST_OS_LINUX || BOOST_OS_ANDROID)
# include "inotify/basic_dir_monitor_service.hpp"
#elif BOOST_OS_MACOS
# include "fsevents/basic_dir_monitor_service.hpp"
#elif BOOST_OS_BSD
# include "kqueue/basic_dir_monitor_service.hpp"
#else
# error "Platform not supported."
#endif

namespace boost {
namespace asio {
namespace boost {
namespace asio {

typedef basic_dir_monitor<basic_dir_monitor_service<> > dir_monitor;
typedef basic_dir_monitor<basic_dir_monitor_service<> > dir_monitor;

}
}
}
}

#endif
153 changes: 153 additions & 0 deletions extras/dirwatch/fsevents/basic_dir_monitor_service.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
//
// Apple FSEvents monitor implementation based on windows monitor_service
// Copyright (c) 2014 Stanislav Karchebnyy <berkus@atta-metta.net>
// Copyright (c) 2008, 2009 Boris Schaeling <boris@highscore.de>
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once

#include "dir_monitor_impl.hpp"
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/filesystem.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#include <string>
#include <stdexcept>

namespace boost {
namespace asio {

template <typename DirMonitorImplementation = dir_monitor_impl>
class basic_dir_monitor_service
: public boost::asio::io_service::service
{
public:
static boost::asio::io_service::id id;

explicit basic_dir_monitor_service(boost::asio::io_service &io_service)
: boost::asio::io_service::service(io_service),
async_monitor_work_(new boost::asio::io_service::work(async_monitor_io_service_)),
async_monitor_thread_(boost::bind(&boost::asio::io_service::run, &async_monitor_io_service_))
{
}

~basic_dir_monitor_service()
{
// The async_monitor thread will finish when async_monitor_work_ is reset as all asynchronous
// operations have been aborted and were discarded before (in destroy).
async_monitor_work_.reset();

// Event processing is stopped to discard queued operations.
async_monitor_io_service_.stop();

// The async_monitor thread is joined to make sure the directory monitor service is
// destroyed _after_ the thread is finished (not that the thread tries to access
// instance properties which don't exist anymore).
async_monitor_thread_.join();
}

typedef boost::shared_ptr<DirMonitorImplementation> implementation_type;

void construct(implementation_type &impl)
{
impl.reset(new DirMonitorImplementation());
}

void destroy(implementation_type &impl)
{
// If an asynchronous call is currently waiting for an event
// we must interrupt the blocked call to make sure it returns.
impl->destroy();

impl.reset();
}

void add_directory(implementation_type &impl, const std::string &dirname)
{
boost::filesystem::path dir(boost::filesystem::canonical(dirname));
if (!boost::filesystem::is_directory(dir))
throw std::invalid_argument("boost::asio::basic_dir_monitor_service::add_directory: " + dir.native() + " is not a valid directory entry");

impl->add_directory(dir);
}

void remove_directory(implementation_type &impl, const std::string &dirname)
{
boost::filesystem::path dir(boost::filesystem::canonical(dirname));
impl->remove_directory(dir);
}

/**
* Blocking event monitor.
*/
dir_monitor_event monitor(implementation_type &impl, boost::system::error_code &ec)
{
return impl->popfront_event(ec);
}

template <typename Handler>
class monitor_operation
{
public:
monitor_operation(implementation_type &impl, boost::asio::io_service &io_service, Handler handler)
: impl_(impl),
io_service_(io_service),
work_(io_service),
handler_(handler)
{
}

void operator()() const
{
implementation_type impl = impl_.lock();
if (impl)
{
boost::system::error_code ec;
dir_monitor_event ev = impl->popfront_event(ec);
this->io_service_.post(boost::asio::detail::bind_handler(handler_, ec, ev));
}
else
{
this->io_service_.post(boost::asio::detail::bind_handler(handler_, boost::asio::error::operation_aborted, dir_monitor_event()));
}
}

private:
boost::weak_ptr<DirMonitorImplementation> impl_;
boost::asio::io_service &io_service_;
boost::asio::io_service::work work_;
Handler handler_;
};

/**
* Non-blocking event monitor.
*/
template <typename Handler>
void async_monitor(implementation_type &impl, Handler handler)
{
this->async_monitor_io_service_.post(monitor_operation<Handler>(impl, this->get_io_service(), handler));
}

private:
void shutdown_service() override
{}

boost::asio::io_service async_monitor_io_service_;
boost::scoped_ptr<boost::asio::io_service::work> async_monitor_work_;
boost::thread async_monitor_thread_;
};

template <typename DirMonitorImplementation>
boost::asio::io_service::id basic_dir_monitor_service<DirMonitorImplementation>::id;

} // asio namespace
} // boost namespace

Loading

0 comments on commit e6874fd

Please sign in to comment.