• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Fwd: kqueue issues
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Fwd: kqueue issues


  • Subject: Fwd: kqueue issues
  • From: "Foster Brereton" <email@hidden>
  • Date: Wed, 12 Apr 2006 11:25:50 -0700

Hi all,

Thanks to the carbon-dev list I was directed to kqueues for file
notification support. I am trying to get a general file monitoring
registration mechanism up and running, one that leverages kqueue on
the back end (for MacOS X, anyhow; I'll be porting it to Win32 as well
so it's a cross-platform solution.)

I'm having issues with my kqueue implementation, however. I have looked over
the kqueue man pages and the PDF that comes alongside the
FileNotification example from Apple, still with no success.

The issue that I'm having is that the kevent never comes back telling
me an event has taken place. I have attached my code (it's not long,
and hopefully readable) and am wondering if someone can point out the
critical mistake I am making? I know there are other problems with the
code, but whatever it is that is keeping the kevents from firing is my
highest priority issue right now.

Thanks in advance for the help.

Blessings,
Foster


--
Foster T. Brereton - Computer Scientist
Software Technology Lab, Adobe Systems Incorporated
email@hidden   --   http://opensource.adobe.com
/*
    Copyright 2005-2006 Adobe Systems Incorporated
    Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
    or a copy at http://opensource.adobe.com/licenses.html)
*/

/****************************************************************************************************/

#include <adobe/future/file_monitor.hpp>

#include <adobe/algorithm.hpp>
#include <adobe/functional.hpp>
#include <adobe/once.hpp>

#include <boost/bind.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/thread/thread.hpp>

#include <list>
#include <vector>
#include <stdexcept>
#include <utility>

#include <sys/event.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <unistd.h>

/****************************************************************************************************/

ADOBE_GLOBAL_MUTEX_DEFINITION(file_monitor)

/****************************************************************************************************/

namespace {

/****************************************************************************************************/

inline u_int vnode_events()
{
    return NOTE_DELETE | NOTE_WRITE |
           NOTE_ATTRIB | NOTE_RENAME;
}

/****************************************************************************************************/

int file_monitor_kqueue()
{
    static const int kq(kqueue());

    if (kq < 0)
        throw std::runtime_error("bad kqueue");

    return kq;
}

/****************************************************************************************************/

struct file_t
{
    typedef boost::filesystem::path path_type;

    file_t(const path_type& path, const adobe::monitor_file_callback_t& proc) :
        path_m(path), proc_m(proc)
    {
    	static const timespec timeout = { 0, 0 };

        fd_m = open(path_m.string().c_str(), O_EVTONLY); // WARNING (fbrereto) : is O_EVTONLY HFS+ only? (if so try FREAD)

        EV_SET(&evt_m, fd_m, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, vnode_events(), 0, 0);

        if (kevent(file_monitor_kqueue(), &evt_m, 1, NULL, 0, &timeout) == -1)
            throw std::runtime_error("bad kevent");
    }

    ~file_t()
    {
    	static const timespec timeout = { 0, 0 };

        evt_m.fflags = EV_DELETE;

        if (kevent(file_monitor_kqueue(), &evt_m, 1, NULL, 0, &timeout) == -1)
            throw std::runtime_error("bad kevent");

        (void)close(fd_m);
    }

    path_type                      path_m;
    adobe::monitor_file_callback_t proc_m;
    int                            fd_m;
    struct kevent                  evt_m;
};

typedef std::list<file_t> file_set_t;

/****************************************************************************************************/

file_set_t& file_set_nolock()
{
    static file_set_t file_set_s;

    return file_set_s;
}

/****************************************************************************************************/

inline file_set_t::iterator find_file_nolock(const boost::filesystem::path& path)
{
    return adobe::find_if(file_set_nolock(), boost::bind(adobe::compare_members(&file_t::path_m,
                                                                                std::equal_to<file_t::path_type>()),
                                                         _1, path));
}

/****************************************************************************************************/

void thread_monitor_loop()
{
	static const timespec timeout = { 0, 0 }; //  Time out 30 seconds, we check mpTaskInfo->done at leaset every 30 seconds

    file_set_t& set(file_set_nolock());

    if (!set.empty())
    {
        ADOBE_GLOBAL_MUTEX_INSTANCE(file_monitor);

        int                        set_size(set.size());
        std::vector<struct kevent> ev_receive(set_size);

        while (set_size)
        {
            int ev_count = kevent(file_monitor_kqueue(), NULL, 0, &ev_receive[0], set_size, &timeout); // First call kevent specifying the number of folders to watch

            if (ev_count <= 0)
                break;

            for (int i(0); i < ev_count; ++i)
            {
                struct kevent* kevp = &ev_receive[i];
                if ( kevp->flags == EV_ERROR )
                    throw std::runtime_error("err");;
                //PostKQueueEvent( kevp ); //  Post kevent
            }
        }
    }
}

/****************************************************************************************************/

void thread_monitor_proc()
{
    while (true)
    {
        thread_monitor_loop();
    }
}

/****************************************************************************************************/

} // namespace

/****************************************************************************************************/

namespace adobe {

/****************************************************************************************************/

void monitor(const boost::filesystem::path& path, const monitor_file_callback_t& proc)
{
    if (proc.empty())
        return;

    if (!boost::filesystem::exists(path))
        return;

    static boost::thread::thread monitor_thread(&thread_monitor_proc);

    ADOBE_GLOBAL_MUTEX_INSTANCE(file_monitor);

    file_set_nolock().push_back(file_t(path, proc));
}

/****************************************************************************************************/

bool is_monitored(const boost::filesystem::path& path)
{
    if (!boost::filesystem::exists(path))
        return false;

    ADOBE_GLOBAL_MUTEX_INSTANCE(file_monitor);

    return find_file_nolock(path) != file_set_nolock().end();
}

/****************************************************************************************************/

void unmonitor(const boost::filesystem::path& path)
{
    if (!boost::filesystem::exists(path))
        return;

    ADOBE_GLOBAL_MUTEX_INSTANCE(file_monitor);

    file_set_t&          set(file_set_nolock());
    file_set_t::iterator result(find_file_nolock(path));

    if (result == set.end())
        return;

    set.erase(result);
}

/****************************************************************************************************/

} // namespace adobe

/****************************************************************************************************/

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Prev by Date: Re: Exiting a cthread?
  • Next by Date: Re: waitid() function replacement
  • Previous by thread: Re: Exiting a cthread?
  • Next by thread: Problems building universal binaries using -isysroot
  • Index(es):
    • Date
    • Thread