Merge SOC2009_FSWATCHER branch into trunk.

Merges everything from the branch with only some minor changes, mostly renamed
wxUSE_FSWATCHER_{INOTIFY,KQUEUE} to wxHAS_{INOTIFY,KQUEUE}.

Add wxFileSystemWatcher and related classes.

Also introduces wxEventLoopSource.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62474 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2009-10-22 11:35:43 +00:00
parent 40152925d5
commit 6b8ef0b35d
75 changed files with 69755 additions and 60720 deletions

View File

@@ -14,6 +14,208 @@
#include "wx/event.h"
#include "wx/utils.h"
#include "wx/hashset.h"
// ----------------------------------------------------------------------------
// wxEventLoopSource: source of i/o for wxEventLoop
// ----------------------------------------------------------------------------
#define wxTRACE_EVT_SOURCE "EventSource"
#if defined(__UNIX__) && (wxUSE_CONSOLE_EVENTLOOP || defined(__WXGTK__) || \
defined(__WXOSX_COCOA__))
#define wxUSE_EVENTLOOP_SOURCE 1
#else
#define wxUSE_EVENTLOOP_SOURCE 0
#endif
#if wxUSE_EVENTLOOP_SOURCE
// handler used to process events on event loop sources
class WXDLLIMPEXP_BASE wxEventLoopSourceHandler
{
public:
// called when descriptor is available for non-blocking read
virtual void OnReadWaiting() = 0;
// called when descriptor is available for non-blocking write
virtual void OnWriteWaiting() = 0;
// called when there is exception on descriptor
virtual void OnExceptionWaiting() = 0;
// virtual dtor for the base class
virtual ~wxEventLoopSourceHandler() { }
};
// those flags describes what events should be reported
enum
{
wxEVENT_SOURCE_INPUT = 0x01,
wxEVENT_SOURCE_OUTPUT = 0x02,
wxEVENT_SOURCE_EXCEPTION = 0x04,
wxEVENT_SOURCE_ALL = wxEVENT_SOURCE_INPUT | wxEVENT_SOURCE_OUTPUT |
wxEVENT_SOURCE_EXCEPTION,
};
class wxAbstractEventLoopSource
{
public:
wxAbstractEventLoopSource() :
m_handler(NULL), m_flags(-1)
{}
wxAbstractEventLoopSource(wxEventLoopSourceHandler* handler, int flags) :
m_handler(handler), m_flags(flags)
{}
virtual ~wxAbstractEventLoopSource() { }
virtual bool IsOk() const = 0;
virtual void Invalidate() = 0;
void SetHandler(wxEventLoopSourceHandler* handler)
{
m_handler = handler;
}
wxEventLoopSourceHandler* GetHandler() const
{
return m_handler;
}
void SetFlags(int flags)
{
m_flags = flags;
}
int GetFlags() const
{
return m_flags;
}
protected:
wxEventLoopSourceHandler* m_handler;
int m_flags;
};
// This class is a simple wrapper for OS specific resources than can be a
// source of I/O. On Unix,for instance these are file descriptors.
//
// Instances of this class doesn't take resposibility of any resource you pass
// to them, I.E. you have to release them yourself.
template<class T>
class WXDLLIMPEXP_BASE wxEventLoopSourceBase : public wxAbstractEventLoopSource
{
public:
typedef T Resource;
// copy ctor
wxEventLoopSourceBase(const wxEventLoopSourceBase& source) :
wxAbstractEventLoopSource(source.GetHandler(), source.GetFlags()),
m_res(source.GetResource())
{
}
virtual const T InvalidResource() const
{
return (T)-1;
}
virtual void Invalidate()
{
SetResource(InvalidResource());
SetHandler(NULL);
}
// sets internal value to res
void SetResource(T res)
{
m_res = res;
}
// returns associated resource
T GetResource() const
{
return m_res;
}
virtual bool IsOk() const
{
// flags < 0 are invalid and flags == 0 mean monitoring for nothing
return m_res != InvalidResource() && m_handler && m_flags >=1;
}
protected:
// empty ctor, beacuse we often store event sources as values
wxEventLoopSourceBase() :
wxAbstractEventLoopSource(),
m_res(InvalidResource())
{
}
// ctor setting internal value to the os resource res
wxEventLoopSourceBase(T res, wxEventLoopSourceHandler* handler,
int flags) :
wxAbstractEventLoopSource(handler, flags),
m_res(res)
{ }
T m_res;
};
#if defined(__WXMAC__)
class wxMacEventLoopSource : public wxEventLoopSourceBase<CFRunLoopSourceRef>
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
int GetFileDescriptor() const
{
return m_fd;
}
#endif
protected:
wxMacEventLoopSource() : wxEventLoopSourceBase<CFRunLoopSourceRef>() { }
// ctor setting internal value to the os resource res
wxMacEventLoopSource(CFRunLoopSourceRef res,
wxEventLoopSourceHandler* handler, int flags) :
wxEventLoopSourceBase<CFRunLoopSourceRef>(res, handler, flags)
{
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
int m_fd;
#endif
friend class wxGUIEventLoop;
};
#endif
#if defined(__UNIX__)
class wxUnixEventLoopSource : public wxEventLoopSourceBase<int>
{
protected:
wxUnixEventLoopSource() : wxEventLoopSourceBase<int>() { }
// ctor setting internal value to the os resource res
wxUnixEventLoopSource(int res, wxEventLoopSourceHandler* handler,
int flags) :
wxEventLoopSourceBase<int>(res, handler, flags)
{
}
friend class wxConsoleEventLoop;
friend class wxGUIEventLoop;
};
#endif
// the list of watched sources
WX_DECLARE_HASH_SET(wxAbstractEventLoopSource*, wxPointerHash, wxPointerEqual,
wxEventLoopSourceHashSet);
#endif
/*
NOTE ABOUT wxEventLoopBase::YieldFor LOGIC
@@ -64,6 +266,68 @@ public:
// returns true if this is the main loop
bool IsMain() const;
#if wxUSE_EVENTLOOP_SOURCE
virtual wxAbstractEventLoopSource* CreateSource() const = 0;
virtual wxAbstractEventLoopSource* CreateSource(int WXUNUSED(res),
wxEventLoopSourceHandler* WXUNUSED(handler),
int WXUNUSED(flags)) const
{
return NULL;
}
// adds source to be monitored for I/O events specified in flags. Upon an
// event the appropriate method of handler will be called. The handler is
// owned be the calling client and will not be freed in any case.
// Returns true if the source was successfully added, false if it failed
// (this may happen for example when this source is already monitored)
virtual bool AddSource(wxAbstractEventLoopSource* source)
{
wxCHECK_MSG( source && source->IsOk(), false, "Invalid source" );
wxEventLoopSourceHashSet::value_type val(source);
if (!m_sourceMap.insert(val).second)
{
return false;
}
bool ret = DoAddSource(source);
if (!ret)
{
(void) m_sourceMap.erase(source);
}
return ret;
}
// removes the source from the list of monitored sources.
// Returns true if the source was successfully removed, false otherwise
virtual bool RemoveSource(wxAbstractEventLoopSource* source)
{
wxCHECK_MSG( source && source->IsOk(), false, "Invalid source" );
if (m_sourceMap.find(source) == m_sourceMap.end())
{
return false;
}
bool ret = DoRemoveSource(source);
m_sourceMap.erase(source);
return ret;
}
bool RemoveAllSources()
{
wxEventLoopSourceHashSet::iterator it = m_sourceMap.begin();
while ( !m_sourceMap.empty() )
{
(void) RemoveSource(*it);
m_sourceMap.erase(it);
it = m_sourceMap.begin();
}
return true;
}
#endif
// dispatch&processing
// -------------------
@@ -114,25 +378,25 @@ public:
// Yield-related hooks
// -------------------
// process all currently pending events right now
//
// it is an error to call Yield() recursively unless the value of
// onlyIfNeeded is true
//
// WARNING: this function is dangerous as it can lead to unexpected
// reentrancies (i.e. when called from an event handler it
// may result in calling the same event handler again), use
// with _extreme_ care or, better, don't use at all!
// process all currently pending events right now
//
// it is an error to call Yield() recursively unless the value of
// onlyIfNeeded is true
//
// WARNING: this function is dangerous as it can lead to unexpected
// reentrancies (i.e. when called from an event handler it
// may result in calling the same event handler again), use
// with _extreme_ care or, better, don't use at all!
bool Yield(bool onlyIfNeeded = false);
virtual bool YieldFor(long eventsToProcess) = 0;
// returns true if the main thread is inside a Yield() call
// returns true if the main thread is inside a Yield() call
virtual bool IsYielding() const
{ return m_isInsideYield; }
// returns true if events of the given event category should be immediately
// processed inside a wxApp::Yield() call or rather should be queued for
// later processing by the main event loop
// returns true if events of the given event category should be immediately
// processed inside a wxApp::Yield() call or rather should be queued for
// later processing by the main event loop
virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const
{ return (m_eventsToProcessInsideYield & cat) != 0; }
@@ -150,6 +414,13 @@ public:
protected:
#if wxUSE_EVENTLOOP_SOURCE
virtual bool DoAddSource(wxAbstractEventLoopSource* source) = 0;
virtual bool DoRemoveSource(wxAbstractEventLoopSource* source) = 0;
wxEventLoopSourceHashSet m_sourceMap;
#endif
// this function should be called before the event loop terminates, whether
// this happens normally (because of Exit() call) or abnormally (because of
// an exception thrown from inside the loop)
@@ -223,7 +494,7 @@ private:
#include "wx/cocoa/evtloop.h"
#elif defined(__WXDFB__)
#include "wx/dfb/evtloop.h"
#elif defined(__WXGTK20__)
#elif defined(__WXGTK__)
#include "wx/gtk/evtloop.h"
#else // other platform