Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warning fixes, cleanup, and autorelease pools #10

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4879a00
Fix warnings.
tiennou Aug 31, 2013
25b7e7e
Cleanup nested if.
tiennou Aug 31, 2013
210cc5f
Log errno and exit if `kevent` fails.
tiennou Aug 31, 2013
d643f2d
Add an autorelease pool.
tiennou Aug 31, 2013
7d7733e
fix pedantic warnings
pilotmoon Dec 20, 2013
bd8bad7
Set NSThread name, for debugging purposes.
dwarfland Dec 26, 2013
8951fe1
Use keyed subscripting for clarity
antmd Jan 28, 2014
4fcf6cd
Added ARC compatibility macros and type modifiers
Feb 6, 2014
6708789
Make use of ARC Macros and fix missing NSWorkspace on iOS
Feb 6, 2014
f9a1d7d
Indentation
Feb 6, 2014
c357581
Added additional ARC macros
Feb 6, 2014
545e0b9
Changed misplaced release to retain
Feb 6, 2014
11e0331
added iOS thread sleep possibilities
Feb 6, 2014
0e988cd
Added iOS thread sleep possibilities
Feb 6, 2014
faa504a
changed _sleepInterval type to NSTimeInterval
Feb 6, 2014
053ffeb
changed sleepInterval property type to NSTimeInterval
Feb 7, 2014
7fb9f22
gitignore
Feb 12, 2014
e6c9712
Remove NSWorkspace references.
natestedman Feb 27, 2014
ed75f6d
Merge remote-tracking branch 'refs/remotes/invariant/master'
michal-tomlein Jun 12, 2014
42fe0ea
Merge remote-tracking branch 'refs/remotes/quicksilver/master'
michal-tomlein Jun 13, 2014
700b245
Merge remote-tracking branch 'refs/remotes/natestedman/master'
michal-tomlein Jun 13, 2014
c147c6f
Merge remote-tracking branch 'refs/remotes/antmd/master'
michal-tomlein Jun 13, 2014
894bc7b
Merge remote-tracking branch 'refs/remotes/remobjects/master'
michal-tomlein Jun 13, 2014
34e73dc
Clean up, use modern Objective-C features and conventions, require ARC
michal-tomlein Jun 13, 2014
0a1366c
Clean up nested ifs
michal-tomlein Jun 13, 2014
0a7dd8b
Replace the VDKQueueNotifyAbout #defines with an enum (VDKQueueEvent)
michal-tomlein Jun 13, 2014
503c187
Allow the queue to be changed
tiennou Apr 18, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### OSX ###
.DS_Store
.AppleDouble
.LSOverride

# Icon must ends with two \r.
Icon


# Thumbnails
._*

# Files that might appear on external disk
.Spotlight-V100
.Trashes


### Xcode ###
build
*.xcodeproj/*
!*.xcodeproj/project.pbxproj
!*.xcworkspace/contents.xcworkspacedata

43 changes: 14 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
VDKQueue
=======
========

A modern, faster, better version of UKKQueue.

<http://incident57.com/codekit>


about
About
-----

VDKQueue is an Objective-C wrapper around kernel queues (kQueues).
Expand All @@ -15,19 +14,17 @@ It allows you to watch a file or folder for changes and be notified when they oc
VDKQueue is a modern, streamlined and much faster version of UKKQueue, which was originally written in 2003 by Uli Kusterer.
Objective-C has come a long way in the past nine years and UKKQueue was long in the tooth. VDKQueue is better in several ways:

-- The number of method calls is vastly reduced.
-- Grand Central Dispatch is used in place of Uli's "threadProxy" notifications (much faster)
-- Memory footprint is roughly halved, since VDKQueue creates less overhead
-- Fewer locks are taken, especially in loops (faster)
-- The code is *much* cleaner and simpler!
-- There is only one .h and one .m file to include.
- The number of method calls is vastly reduced.
- Grand Central Dispatch is used in place of Uli's "threadProxy" notifications (much faster)
- Memory footprint is roughly halved, since VDKQueue creates less overhead
- Fewer locks are taken, especially in loops (faster)
- The code is *much* cleaner and simpler!
- There is only one .h and one .m file to include.

VDKQueue also fixes long-standing bugs in UKKQueue. For example: OS X limits the number of open file descriptors each process
may have to about 3,000. If UKKQueue fails to open a new file descriptor because it has hit this limit, it will crash. VDKQueue will not.



performance

Performance
-----------

Adding 1,945 file paths to a UKKQueue instance took, on average, 80ms.
Expand All @@ -37,22 +34,12 @@ VDKQueue processes and pushes out notifications about file changes roughly 50-70

All tests conducted on a 2008 MacBook Pro 2.5Ghz with 4GB of RAM running OS 10.7.3 using Xcode and Instruments (time profiler).




requirements
Requirements
------------

VDKQueue requires Mac OS X 10.6+ because it uses Grand Central Dispatch.

VDKQueue does not support garbage collection. If you use garbage collection, you are lazy. Shape up.
VDKQueue requires Mac OS X 10.6+ because it uses Grand Central Dispatch. VDKQueue uses ARC.

VDKQueue does not currently use ARC, although it should be straightforward to convert if you wish. (Don't be the guy that can't manually manage memory, though.)




license
License
-------

Created by Bryan D K Jones on 28 March 2012
Expand All @@ -63,7 +50,5 @@ Based heavily on UKKQueue, which was created and copyrighted by Uli Kusterer on
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.

2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.

3. This notice may not be removed or altered from any source distribution.
177 changes: 92 additions & 85 deletions VDKQueue.h
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
// VDKQueue.h
// Created by Bryan D K Jones on 28 March 2012
// Copyright 2013 Bryan D K Jones
// VDKQueue.h
// Created by Bryan D K Jones on 28 March 2012
// Copyright 2013 Bryan D K Jones
//
// Based heavily on UKKQueue, which was created and copyrighted by Uli Kusterer on 21 Dec 2003.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source
// distribution.
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source
// distribution.

//
// BASED ON UKKQUEUE:
//
// This is an updated, modernized and streamlined version of the excellent UKKQueue class, which was authored by Uli Kusterer.
// UKKQueue was written back in 2003 and there have been many, many improvements to Objective-C since then. VDKQueue uses the
// UKKQueue was written back in 2003 and there have been many, many improvements to Objective-C since then. VDKQueue uses the
// core of Uli's original class, but makes it faster and more efficient. Method calls are reduced. Grand Central Dispatch is used in place
// of Uli's "threadProxy" objects. The memory footprint is roughly halved, as I don't create the overhead that UKKQueue does.
//
// VDKQueue is also simplified. The option to use it as a singleton is removed. You simply alloc/init an instance and add paths you want to
// watch. Your objects can be alerted to changes either by notifications or by a delegate method (or both). See below.
// watch. Your objects can be alerted to changes either by notifications or by a delegate method (or both). See below.
//
// It also fixes several bugs. For one, it won't crash if it can't create a file descriptor to a file you ask it to watch. (By default, an OS X process can only
// have about 3,000 file descriptors open at once. If you hit that limit, UKKQueue will crash. VDKQueue will not.)
//

//
// DEPENDENCIES:
//
// DEPENDENCIES:
//
// VDKQueue requires OS 10.6+ because it relies on Grand Central Dispatch.
//

Expand All @@ -57,94 +57,101 @@
//
// Other frameworks out there try to work around this issue by immediately attempting to re-open the file descriptor to the path. This is not bulletproof and may fail;
// it all depends on the timing of disk I/O. Bottom line: you could not rely on it and might miss future changes to the file path you're supposedly watching. That's why
// VDKQueue does not take this approach, but favors the "manual" method of "stop-watching-then-rewatch".
// VDKQueue does not take this approach, but favors the "manual" method of "stop-watching-then-rewatch".
//



#import <Foundation/Foundation.h>
#include <sys/types.h>

#include <sys/event.h>

/**
* Logical OR these values into the flags that you pass in the @c -addPath:notifyingAbout: method
* to specify the types of notifications you're interested in.
* Pass VDKQueueEventAll to receive all of them.
*/
typedef NS_OPTIONS(unsigned, VDKQueueEvent) {
/// Item was renamed.
VDKQueueEventRename = NOTE_RENAME,

//
// Logical OR these values into the u_int that you pass in the -addPath:notifyingAbout: method
// to specify the types of notifications you're interested in. Pass the default value to receive all of them.
//
#define VDKQueueNotifyAboutRename NOTE_RENAME // Item was renamed.
#define VDKQueueNotifyAboutWrite NOTE_WRITE // Item contents changed (also folder contents changed).
#define VDKQueueNotifyAboutDelete NOTE_DELETE // item was removed.
#define VDKQueueNotifyAboutAttributeChange NOTE_ATTRIB // Item attributes changed.
#define VDKQueueNotifyAboutSizeIncrease NOTE_EXTEND // Item size increased.
#define VDKQueueNotifyAboutLinkCountChanged NOTE_LINK // Item's link count changed.
#define VDKQueueNotifyAboutAccessRevocation NOTE_REVOKE // Access to item was revoked.
/// Item contents changed (also folder contents changed).
VDKQueueEventWrite = NOTE_WRITE,

/// Item was removed.
VDKQueueEventDelete = NOTE_DELETE,

/// Item attributes changed.
VDKQueueEventAttributeChange = NOTE_ATTRIB,

#define VDKQueueNotifyDefault (VDKQueueNotifyAboutRename | VDKQueueNotifyAboutWrite \
| VDKQueueNotifyAboutDelete | VDKQueueNotifyAboutAttributeChange \
| VDKQueueNotifyAboutSizeIncrease | VDKQueueNotifyAboutLinkCountChanged \
| VDKQueueNotifyAboutAccessRevocation)
/// Item size increased.
VDKQueueEventSizeIncrease = NOTE_EXTEND,

/// Item's link count changed.
VDKQueueEventLinkCountChanged = NOTE_LINK,

/// Access to item was revoked.
VDKQueueEventAccessRevocation = NOTE_REVOKE,

/// All events.
VDKQueueEventAll = VDKQueueEventRename
| VDKQueueEventWrite
| VDKQueueEventDelete
| VDKQueueEventAttributeChange
| VDKQueueEventSizeIncrease
| VDKQueueEventLinkCountChanged
| VDKQueueEventAccessRevocation
};

//
// Notifications that this class sends to the NSWORKSPACE notification center.
// Object = the instance of VDKQueue that was watching for changes
// userInfo.path = the file path where the change was observed
//
extern NSString * VDKQueueRenameNotification;
extern NSString * VDKQueueWriteNotification;
extern NSString * VDKQueueDeleteNotification;
extern NSString * VDKQueueAttributeChangeNotification;
extern NSString * VDKQueueSizeIncreaseNotification;
extern NSString * VDKQueueLinkCountChangeNotification;
extern NSString * VDKQueueAccessRevocationNotification;


extern NSString *const VDKQueueRenameNotification;
extern NSString *const VDKQueueWriteNotification;
extern NSString *const VDKQueueDeleteNotification;
extern NSString *const VDKQueueAttributeChangeNotification;
extern NSString *const VDKQueueSizeIncreaseNotification;
extern NSString *const VDKQueueLinkCountChangeNotification;
extern NSString *const VDKQueueAccessRevocationNotification;

//
// Or, instead of subscribing to notifications, you can specify a delegate and implement this method to respond to kQueue events.
// Note the required statement! For speed, this class does not check to make sure the delegate implements this method. (When I say "required" I mean it!)
//

@class VDKQueue;

@protocol VDKQueueDelegate <NSObject>
@required

-(void) VDKQueue:(VDKQueue *)queue receivedNotification:(NSString*)noteName forPath:(NSString*)fpath;
- (void)queue:(VDKQueue *)queue didReceiveNotification:(NSString *)notificationName forPath:(NSString *)fpath;

@end





@interface VDKQueue : NSObject
{
id<VDKQueueDelegate> _delegate;
BOOL _alwaysPostNotifications; // By default, notifications are posted only if there is no delegate set. Set this value to YES to have notes posted even when there is a delegate.

@private
int _coreQueueFD; // The actual kqueue ID (Unix file descriptor).
NSMutableDictionary *_watchedPathEntries; // List of VDKQueuePathEntries. Keys are NSStrings of the path that each VDKQueuePathEntry is for.
BOOL _keepWatcherThreadRunning; // Set to NO to cancel the thread that watches _coreQueueFD for kQueue events
}


//
// Note: there is no need to ask whether a path is already being watched. Just add it or remove it and this class
// will take action only if appropriate. (Add only if we're not already watching it, remove only if we are.)
//
// Warning: You must pass full, root-relative paths. Do not pass tilde-abbreviated paths or file URLs.
//
- (void) addPath:(NSString *)aPath;
- (void) addPath:(NSString *)aPath notifyingAbout:(u_int)flags; // See note above for values to pass in "flags"

- (void) removePath:(NSString *)aPath;
- (void) removeAllPaths;


- (NSUInteger) numberOfWatchedPaths; // Returns the number of paths that this VDKQueue instance is actively watching.

@property (nonatomic, weak) id <VDKQueueDelegate> delegate;
@property (nonatomic, retain) dispatch_queue_t queue;
/**
* By default, notifications are posted only if there is no delegate set.
* Set this value to @c YES to have notes posted even when there is a delegate.
*/
@property (nonatomic) BOOL alwaysPostNotifications;
@property (nonatomic) NSTimeInterval sleepInterval;

/**
* Note: there is no need to ask whether a path is already being watched. Just add it or remove it and this class
* will take action only if appropriate. (Add only if we're not already watching it, remove only if we are.)
*
* Warning: You must pass full, root-relative paths. Do not pass tilde-abbreviated paths or file URLs.
*/
- (void)addPath:(NSString *)aPath;
/// See note above for values to pass in "flags"
- (void)addPath:(NSString *)aPath notifyingAbout:(VDKQueueEvent)flags;

- (void)removePath:(NSString *)aPath;
- (void)removeAllPaths;

/// Returns the number of paths that this VDKQueue instance is actively watching.
- (NSUInteger)numberOfWatchedPaths;


@property (assign) id<VDKQueueDelegate> delegate;
@property (assign) BOOL alwaysPostNotifications;

@end
@end
Loading